Home | History | Annotate | Line # | Download | only in legacy
      1  1.1  christos /*
      2  1.1  christos  * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
      3  1.1  christos  * All rights reserved.
      4  1.1  christos  *
      5  1.1  christos  * This source code is licensed under both the BSD-style license (found in the
      6  1.1  christos  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      7  1.1  christos  * in the COPYING file in the root directory of this source tree).
      8  1.1  christos  * You may select, at your option, one of the above-listed licenses.
      9  1.1  christos  */
     10  1.1  christos 
     11  1.1  christos 
     12  1.1  christos /*- Dependencies -*/
     13  1.1  christos #include <stddef.h>     /* size_t, ptrdiff_t */
     14  1.1  christos #include <string.h>     /* memcpy */
     15  1.1  christos #include <stdlib.h>     /* malloc, free, qsort */
     16  1.1  christos 
     17  1.1  christos #ifndef XXH_STATIC_LINKING_ONLY
     18  1.1  christos #  define XXH_STATIC_LINKING_ONLY    /* XXH64_state_t */
     19  1.1  christos #endif
     20  1.1  christos #include "../common/xxhash.h"                  /* XXH64_* */
     21  1.1  christos #include "zstd_v07.h"
     22  1.1  christos 
     23  1.1  christos #define FSEv07_STATIC_LINKING_ONLY   /* FSEv07_MIN_TABLELOG */
     24  1.1  christos #define HUFv07_STATIC_LINKING_ONLY   /* HUFv07_TABLELOG_ABSOLUTEMAX */
     25  1.1  christos #define ZSTDv07_STATIC_LINKING_ONLY
     26  1.1  christos 
     27  1.1  christos #include "../common/compiler.h"
     28  1.1  christos #include "../common/error_private.h"
     29  1.1  christos 
     30  1.1  christos 
     31  1.1  christos #ifdef ZSTDv07_STATIC_LINKING_ONLY
     32  1.1  christos 
     33  1.1  christos /* ====================================================================================
     34  1.1  christos  * The definitions in this section are considered experimental.
     35  1.1  christos  * They should never be used with a dynamic library, as they may change in the future.
     36  1.1  christos  * They are provided for advanced usages.
     37  1.1  christos  * Use them only in association with static linking.
     38  1.1  christos  * ==================================================================================== */
     39  1.1  christos 
     40  1.1  christos /*--- Constants ---*/
     41  1.1  christos #define ZSTDv07_MAGIC_SKIPPABLE_START  0x184D2A50U
     42  1.1  christos 
     43  1.1  christos #define ZSTDv07_WINDOWLOG_MAX_32  25
     44  1.1  christos #define ZSTDv07_WINDOWLOG_MAX_64  27
     45  1.1  christos #define ZSTDv07_WINDOWLOG_MAX    ((U32)(MEM_32bits() ? ZSTDv07_WINDOWLOG_MAX_32 : ZSTDv07_WINDOWLOG_MAX_64))
     46  1.1  christos #define ZSTDv07_WINDOWLOG_MIN     18
     47  1.1  christos #define ZSTDv07_CHAINLOG_MAX     (ZSTDv07_WINDOWLOG_MAX+1)
     48  1.1  christos #define ZSTDv07_CHAINLOG_MIN       4
     49  1.1  christos #define ZSTDv07_HASHLOG_MAX       ZSTDv07_WINDOWLOG_MAX
     50  1.1  christos #define ZSTDv07_HASHLOG_MIN       12
     51  1.1  christos #define ZSTDv07_HASHLOG3_MAX      17
     52  1.1  christos #define ZSTDv07_SEARCHLOG_MAX    (ZSTDv07_WINDOWLOG_MAX-1)
     53  1.1  christos #define ZSTDv07_SEARCHLOG_MIN      1
     54  1.1  christos #define ZSTDv07_SEARCHLENGTH_MAX   7
     55  1.1  christos #define ZSTDv07_SEARCHLENGTH_MIN   3
     56  1.1  christos #define ZSTDv07_TARGETLENGTH_MIN   4
     57  1.1  christos #define ZSTDv07_TARGETLENGTH_MAX 999
     58  1.1  christos 
     59  1.1  christos #define ZSTDv07_FRAMEHEADERSIZE_MAX 18    /* for static allocation */
     60  1.1  christos static const size_t ZSTDv07_frameHeaderSize_min = 5;
     61  1.1  christos static const size_t ZSTDv07_frameHeaderSize_max = ZSTDv07_FRAMEHEADERSIZE_MAX;
     62  1.1  christos static const size_t ZSTDv07_skippableHeaderSize = 8;  /* magic number + skippable frame length */
     63  1.1  christos 
     64  1.1  christos 
     65  1.1  christos /* custom memory allocation functions */
     66  1.1  christos typedef void* (*ZSTDv07_allocFunction) (void* opaque, size_t size);
     67  1.1  christos typedef void  (*ZSTDv07_freeFunction) (void* opaque, void* address);
     68  1.1  christos typedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customFree; void* opaque; } ZSTDv07_customMem;
     69  1.1  christos 
     70  1.1  christos 
     71  1.1  christos /*--- Advanced Decompression functions ---*/
     72  1.1  christos 
     73  1.1  christos /*! ZSTDv07_estimateDCtxSize() :
     74  1.1  christos  *  Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */
     75  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);
     76  1.1  christos 
     77  1.1  christos /*! ZSTDv07_createDCtx_advanced() :
     78  1.1  christos  *  Create a ZSTD decompression context using external alloc and free functions */
     79  1.1  christos ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);
     80  1.1  christos 
     81  1.1  christos /*! ZSTDv07_sizeofDCtx() :
     82  1.1  christos  *  Gives the amount of memory used by a given ZSTDv07_DCtx */
     83  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);
     84  1.1  christos 
     85  1.1  christos 
     86  1.1  christos /* ******************************************************************
     87  1.1  christos *  Buffer-less streaming functions (synchronous mode)
     88  1.1  christos ********************************************************************/
     89  1.1  christos 
     90  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);
     91  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);
     92  1.1  christos ZSTDLIBv07_API void   ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);
     93  1.1  christos 
     94  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);
     95  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
     96  1.1  christos 
     97  1.1  christos /*
     98  1.1  christos   Buffer-less streaming decompression (synchronous mode)
     99  1.1  christos 
    100  1.1  christos   A ZSTDv07_DCtx object is required to track streaming operations.
    101  1.1  christos   Use ZSTDv07_createDCtx() / ZSTDv07_freeDCtx() to manage it.
    102  1.1  christos   A ZSTDv07_DCtx object can be re-used multiple times.
    103  1.1  christos 
    104  1.1  christos   First optional operation is to retrieve frame parameters, using ZSTDv07_getFrameParams(), which doesn't consume the input.
    105  1.1  christos   It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`),
    106  1.1  christos   and optionally the final size of uncompressed content.
    107  1.1  christos   (Note : content size is an optional info that may not be present. 0 means : content size unknown)
    108  1.1  christos   Frame parameters are extracted from the beginning of compressed frame.
    109  1.1  christos   The amount of data to read is variable, from ZSTDv07_frameHeaderSize_min to ZSTDv07_frameHeaderSize_max (so if `srcSize` >= ZSTDv07_frameHeaderSize_max, it will always work)
    110  1.1  christos   If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.
    111  1.1  christos   Result : 0 when successful, it means the ZSTDv07_frameParams structure has been filled.
    112  1.1  christos           >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.
    113  1.1  christos            errorCode, which can be tested using ZSTDv07_isError()
    114  1.1  christos 
    115  1.1  christos   Start decompression, with ZSTDv07_decompressBegin() or ZSTDv07_decompressBegin_usingDict().
    116  1.1  christos   Alternatively, you can copy a prepared context, using ZSTDv07_copyDCtx().
    117  1.1  christos 
    118  1.1  christos   Then use ZSTDv07_nextSrcSizeToDecompress() and ZSTDv07_decompressContinue() alternatively.
    119  1.1  christos   ZSTDv07_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv07_decompressContinue().
    120  1.1  christos   ZSTDv07_decompressContinue() requires this exact amount of bytes, or it will fail.
    121  1.1  christos 
    122  1.1  christos   @result of ZSTDv07_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
    123  1.1  christos   It can be zero, which is not an error; it just means ZSTDv07_decompressContinue() has decoded some header.
    124  1.1  christos 
    125  1.1  christos   ZSTDv07_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.
    126  1.1  christos   They should preferably be located contiguously, prior to current block.
    127  1.1  christos   Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.
    128  1.1  christos   ZSTDv07_decompressContinue() is very sensitive to contiguity,
    129  1.1  christos   if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
    130  1.1  christos     or that previous contiguous segment is large enough to properly handle maximum back-reference.
    131  1.1  christos 
    132  1.1  christos   A frame is fully decoded when ZSTDv07_nextSrcSizeToDecompress() returns zero.
    133  1.1  christos   Context can then be reset to start a new decompression.
    134  1.1  christos 
    135  1.1  christos 
    136  1.1  christos   == Special case : skippable frames ==
    137  1.1  christos 
    138  1.1  christos   Skippable frames allow the integration of user-defined data into a flow of concatenated frames.
    139  1.1  christos   Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following:
    140  1.1  christos   a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
    141  1.1  christos   b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
    142  1.1  christos   c) Frame Content - any content (User Data) of length equal to Frame Size
    143  1.1  christos   For skippable frames ZSTDv07_decompressContinue() always returns 0.
    144  1.1  christos   For skippable frames ZSTDv07_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
    145  1.1  christos   It also returns Frame Size as fparamsPtr->frameContentSize.
    146  1.1  christos */
    147  1.1  christos 
    148  1.1  christos 
    149  1.1  christos /* **************************************
    150  1.1  christos *  Block functions
    151  1.1  christos ****************************************/
    152  1.1  christos /*! Block functions produce and decode raw zstd blocks, without frame metadata.
    153  1.1  christos     Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
    154  1.1  christos     User will have to take in charge required information to regenerate data, such as compressed and content sizes.
    155  1.1  christos 
    156  1.1  christos     A few rules to respect :
    157  1.1  christos     - Compressing and decompressing require a context structure
    158  1.1  christos       + Use ZSTDv07_createCCtx() and ZSTDv07_createDCtx()
    159  1.1  christos     - It is necessary to init context before starting
    160  1.1  christos       + compression : ZSTDv07_compressBegin()
    161  1.1  christos       + decompression : ZSTDv07_decompressBegin()
    162  1.1  christos       + variants _usingDict() are also allowed
    163  1.1  christos       + copyCCtx() and copyDCtx() work too
    164  1.1  christos     - Block size is limited, it must be <= ZSTDv07_getBlockSizeMax()
    165  1.1  christos       + If you need to compress more, cut data into multiple blocks
    166  1.1  christos       + Consider using the regular ZSTDv07_compress() instead, as frame metadata costs become negligible when source size is large.
    167  1.1  christos     - When a block is considered not compressible enough, ZSTDv07_compressBlock() result will be zero.
    168  1.1  christos       In which case, nothing is produced into `dst`.
    169  1.1  christos       + User must test for such outcome and deal directly with uncompressed data
    170  1.1  christos       + ZSTDv07_decompressBlock() doesn't accept uncompressed data as input !!!
    171  1.1  christos       + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.
    172  1.1  christos         Use ZSTDv07_insertBlock() in such a case.
    173  1.1  christos */
    174  1.1  christos 
    175  1.1  christos #define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)   /* define, for static allocation */
    176  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
    177  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert block into `dctx` history. Useful for uncompressed blocks */
    178  1.1  christos 
    179  1.1  christos 
    180  1.1  christos #endif   /* ZSTDv07_STATIC_LINKING_ONLY */
    181  1.1  christos 
    182  1.1  christos 
    183  1.1  christos /* ******************************************************************
    184  1.1  christos    mem.h
    185  1.1  christos    low-level memory access routines
    186  1.1  christos    Copyright (C) 2013-2015, Yann Collet.
    187  1.1  christos 
    188  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
    189  1.1  christos 
    190  1.1  christos    Redistribution and use in source and binary forms, with or without
    191  1.1  christos    modification, are permitted provided that the following conditions are
    192  1.1  christos    met:
    193  1.1  christos 
    194  1.1  christos        * Redistributions of source code must retain the above copyright
    195  1.1  christos    notice, this list of conditions and the following disclaimer.
    196  1.1  christos        * Redistributions in binary form must reproduce the above
    197  1.1  christos    copyright notice, this list of conditions and the following disclaimer
    198  1.1  christos    in the documentation and/or other materials provided with the
    199  1.1  christos    distribution.
    200  1.1  christos 
    201  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    202  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    203  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    204  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    205  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    206  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    207  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    208  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    209  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    210  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    211  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    212  1.1  christos 
    213  1.1  christos     You can contact the author at :
    214  1.1  christos     - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
    215  1.1  christos     - Public forum : https://groups.google.com/forum/#!forum/lz4c
    216  1.1  christos ****************************************************************** */
    217  1.1  christos #ifndef MEM_H_MODULE
    218  1.1  christos #define MEM_H_MODULE
    219  1.1  christos 
    220  1.1  christos #if defined (__cplusplus)
    221  1.1  christos extern "C" {
    222  1.1  christos #endif
    223  1.1  christos 
    224  1.1  christos /*-****************************************
    225  1.1  christos *  Compiler specifics
    226  1.1  christos ******************************************/
    227  1.1  christos #if defined(_MSC_VER)   /* Visual Studio */
    228  1.1  christos #   include <stdlib.h>  /* _byteswap_ulong */
    229  1.1  christos #   include <intrin.h>  /* _byteswap_* */
    230  1.1  christos #endif
    231  1.1  christos 
    232  1.1  christos 
    233  1.1  christos /*-**************************************************************
    234  1.1  christos *  Basic Types
    235  1.1  christos *****************************************************************/
    236  1.1  christos #if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
    237  1.1  christos # if defined(_AIX)
    238  1.1  christos #  include <inttypes.h>
    239  1.1  christos # else
    240  1.1  christos #  include <stdint.h> /* intptr_t */
    241  1.1  christos # endif
    242  1.1  christos   typedef  uint8_t BYTE;
    243  1.1  christos   typedef uint16_t U16;
    244  1.1  christos   typedef  int16_t S16;
    245  1.1  christos   typedef uint32_t U32;
    246  1.1  christos   typedef  int32_t S32;
    247  1.1  christos   typedef uint64_t U64;
    248  1.1  christos   typedef  int64_t S64;
    249  1.1  christos #else
    250  1.1  christos   typedef unsigned char       BYTE;
    251  1.1  christos   typedef unsigned short      U16;
    252  1.1  christos   typedef   signed short      S16;
    253  1.1  christos   typedef unsigned int        U32;
    254  1.1  christos   typedef   signed int        S32;
    255  1.1  christos   typedef unsigned long long  U64;
    256  1.1  christos   typedef   signed long long  S64;
    257  1.1  christos #endif
    258  1.1  christos 
    259  1.1  christos 
    260  1.1  christos /*-**************************************************************
    261  1.1  christos *  Memory I/O
    262  1.1  christos *****************************************************************/
    263  1.1  christos 
    264  1.1  christos MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
    265  1.1  christos MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
    266  1.1  christos 
    267  1.1  christos MEM_STATIC unsigned MEM_isLittleEndian(void)
    268  1.1  christos {
    269  1.1  christos     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
    270  1.1  christos     return one.c[0];
    271  1.1  christos }
    272  1.1  christos 
    273  1.1  christos MEM_STATIC U16 MEM_read16(const void* memPtr)
    274  1.1  christos {
    275  1.1  christos     U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
    276  1.1  christos }
    277  1.1  christos 
    278  1.1  christos MEM_STATIC U32 MEM_read32(const void* memPtr)
    279  1.1  christos {
    280  1.1  christos     U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
    281  1.1  christos }
    282  1.1  christos 
    283  1.1  christos MEM_STATIC U64 MEM_read64(const void* memPtr)
    284  1.1  christos {
    285  1.1  christos     U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
    286  1.1  christos }
    287  1.1  christos 
    288  1.1  christos MEM_STATIC void MEM_write16(void* memPtr, U16 value)
    289  1.1  christos {
    290  1.1  christos     memcpy(memPtr, &value, sizeof(value));
    291  1.1  christos }
    292  1.1  christos 
    293  1.1  christos MEM_STATIC U32 MEM_swap32(U32 in)
    294  1.1  christos {
    295  1.1  christos #if defined(_MSC_VER)     /* Visual Studio */
    296  1.1  christos     return _byteswap_ulong(in);
    297  1.1  christos #elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
    298  1.1  christos     return __builtin_bswap32(in);
    299  1.1  christos #else
    300  1.1  christos     return  ((in << 24) & 0xff000000 ) |
    301  1.1  christos             ((in <<  8) & 0x00ff0000 ) |
    302  1.1  christos             ((in >>  8) & 0x0000ff00 ) |
    303  1.1  christos             ((in >> 24) & 0x000000ff );
    304  1.1  christos #endif
    305  1.1  christos }
    306  1.1  christos 
    307  1.1  christos MEM_STATIC U64 MEM_swap64(U64 in)
    308  1.1  christos {
    309  1.1  christos #if defined(_MSC_VER)     /* Visual Studio */
    310  1.1  christos     return _byteswap_uint64(in);
    311  1.1  christos #elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
    312  1.1  christos     return __builtin_bswap64(in);
    313  1.1  christos #else
    314  1.1  christos     return  ((in << 56) & 0xff00000000000000ULL) |
    315  1.1  christos             ((in << 40) & 0x00ff000000000000ULL) |
    316  1.1  christos             ((in << 24) & 0x0000ff0000000000ULL) |
    317  1.1  christos             ((in << 8)  & 0x000000ff00000000ULL) |
    318  1.1  christos             ((in >> 8)  & 0x00000000ff000000ULL) |
    319  1.1  christos             ((in >> 24) & 0x0000000000ff0000ULL) |
    320  1.1  christos             ((in >> 40) & 0x000000000000ff00ULL) |
    321  1.1  christos             ((in >> 56) & 0x00000000000000ffULL);
    322  1.1  christos #endif
    323  1.1  christos }
    324  1.1  christos 
    325  1.1  christos 
    326  1.1  christos /*=== Little endian r/w ===*/
    327  1.1  christos 
    328  1.1  christos MEM_STATIC U16 MEM_readLE16(const void* memPtr)
    329  1.1  christos {
    330  1.1  christos     if (MEM_isLittleEndian())
    331  1.1  christos         return MEM_read16(memPtr);
    332  1.1  christos     else {
    333  1.1  christos         const BYTE* p = (const BYTE*)memPtr;
    334  1.1  christos         return (U16)(p[0] + (p[1]<<8));
    335  1.1  christos     }
    336  1.1  christos }
    337  1.1  christos 
    338  1.1  christos MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
    339  1.1  christos {
    340  1.1  christos     if (MEM_isLittleEndian()) {
    341  1.1  christos         MEM_write16(memPtr, val);
    342  1.1  christos     } else {
    343  1.1  christos         BYTE* p = (BYTE*)memPtr;
    344  1.1  christos         p[0] = (BYTE)val;
    345  1.1  christos         p[1] = (BYTE)(val>>8);
    346  1.1  christos     }
    347  1.1  christos }
    348  1.1  christos 
    349  1.1  christos MEM_STATIC U32 MEM_readLE32(const void* memPtr)
    350  1.1  christos {
    351  1.1  christos     if (MEM_isLittleEndian())
    352  1.1  christos         return MEM_read32(memPtr);
    353  1.1  christos     else
    354  1.1  christos         return MEM_swap32(MEM_read32(memPtr));
    355  1.1  christos }
    356  1.1  christos 
    357  1.1  christos 
    358  1.1  christos MEM_STATIC U64 MEM_readLE64(const void* memPtr)
    359  1.1  christos {
    360  1.1  christos     if (MEM_isLittleEndian())
    361  1.1  christos         return MEM_read64(memPtr);
    362  1.1  christos     else
    363  1.1  christos         return MEM_swap64(MEM_read64(memPtr));
    364  1.1  christos }
    365  1.1  christos 
    366  1.1  christos MEM_STATIC size_t MEM_readLEST(const void* memPtr)
    367  1.1  christos {
    368  1.1  christos     if (MEM_32bits())
    369  1.1  christos         return (size_t)MEM_readLE32(memPtr);
    370  1.1  christos     else
    371  1.1  christos         return (size_t)MEM_readLE64(memPtr);
    372  1.1  christos }
    373  1.1  christos 
    374  1.1  christos 
    375  1.1  christos 
    376  1.1  christos #if defined (__cplusplus)
    377  1.1  christos }
    378  1.1  christos #endif
    379  1.1  christos 
    380  1.1  christos #endif /* MEM_H_MODULE */
    381  1.1  christos /* ******************************************************************
    382  1.1  christos    bitstream
    383  1.1  christos    Part of FSE library
    384  1.1  christos    header file (to include)
    385  1.1  christos    Copyright (C) 2013-2016, Yann Collet.
    386  1.1  christos 
    387  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
    388  1.1  christos 
    389  1.1  christos    Redistribution and use in source and binary forms, with or without
    390  1.1  christos    modification, are permitted provided that the following conditions are
    391  1.1  christos    met:
    392  1.1  christos 
    393  1.1  christos        * Redistributions of source code must retain the above copyright
    394  1.1  christos    notice, this list of conditions and the following disclaimer.
    395  1.1  christos        * Redistributions in binary form must reproduce the above
    396  1.1  christos    copyright notice, this list of conditions and the following disclaimer
    397  1.1  christos    in the documentation and/or other materials provided with the
    398  1.1  christos    distribution.
    399  1.1  christos 
    400  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    401  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    402  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    403  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    404  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    405  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    406  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    407  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    408  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    409  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    410  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    411  1.1  christos 
    412  1.1  christos    You can contact the author at :
    413  1.1  christos    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
    414  1.1  christos ****************************************************************** */
    415  1.1  christos #ifndef BITSTREAM_H_MODULE
    416  1.1  christos #define BITSTREAM_H_MODULE
    417  1.1  christos 
    418  1.1  christos #if defined (__cplusplus)
    419  1.1  christos extern "C" {
    420  1.1  christos #endif
    421  1.1  christos 
    422  1.1  christos 
    423  1.1  christos /*
    424  1.1  christos *  This API consists of small unitary functions, which must be inlined for best performance.
    425  1.1  christos *  Since link-time-optimization is not available for all compilers,
    426  1.1  christos *  these functions are defined into a .h to be included.
    427  1.1  christos */
    428  1.1  christos 
    429  1.1  christos 
    430  1.1  christos /*=========================================
    431  1.1  christos *  Target specific
    432  1.1  christos =========================================*/
    433  1.1  christos #if defined(__BMI__) && defined(__GNUC__)
    434  1.1  christos #  include <immintrin.h>   /* support for bextr (experimental) */
    435  1.1  christos #endif
    436  1.1  christos 
    437  1.1  christos /*-********************************************
    438  1.1  christos *  bitStream decoding API (read backward)
    439  1.1  christos **********************************************/
    440  1.1  christos typedef struct
    441  1.1  christos {
    442  1.1  christos     size_t   bitContainer;
    443  1.1  christos     unsigned bitsConsumed;
    444  1.1  christos     const char* ptr;
    445  1.1  christos     const char* start;
    446  1.1  christos } BITv07_DStream_t;
    447  1.1  christos 
    448  1.1  christos typedef enum { BITv07_DStream_unfinished = 0,
    449  1.1  christos                BITv07_DStream_endOfBuffer = 1,
    450  1.1  christos                BITv07_DStream_completed = 2,
    451  1.1  christos                BITv07_DStream_overflow = 3 } BITv07_DStream_status;  /* result of BITv07_reloadDStream() */
    452  1.1  christos                /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
    453  1.1  christos 
    454  1.1  christos MEM_STATIC size_t   BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
    455  1.1  christos MEM_STATIC size_t   BITv07_readBits(BITv07_DStream_t* bitD, unsigned nbBits);
    456  1.1  christos MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD);
    457  1.1  christos MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* bitD);
    458  1.1  christos 
    459  1.1  christos 
    460  1.1  christos 
    461  1.1  christos /*-****************************************
    462  1.1  christos *  unsafe API
    463  1.1  christos ******************************************/
    464  1.1  christos MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);
    465  1.1  christos /* faster, but works only if nbBits >= 1 */
    466  1.1  christos 
    467  1.1  christos 
    468  1.1  christos 
    469  1.1  christos /*-**************************************************************
    470  1.1  christos *  Internal functions
    471  1.1  christos ****************************************************************/
    472  1.1  christos MEM_STATIC unsigned BITv07_highbit32 (U32 val)
    473  1.1  christos {
    474  1.1  christos #   if defined(_MSC_VER)   /* Visual */
    475  1.1  christos     unsigned long r;
    476  1.1  christos     return _BitScanReverse(&r, val) ? (unsigned)r : 0;
    477  1.1  christos #   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */
    478  1.1  christos     return __builtin_clz (val) ^ 31;
    479  1.1  christos #   else   /* Software version */
    480  1.1  christos     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 };
    481  1.1  christos     U32 v = val;
    482  1.1  christos     v |= v >> 1;
    483  1.1  christos     v |= v >> 2;
    484  1.1  christos     v |= v >> 4;
    485  1.1  christos     v |= v >> 8;
    486  1.1  christos     v |= v >> 16;
    487  1.1  christos     return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
    488  1.1  christos #   endif
    489  1.1  christos }
    490  1.1  christos 
    491  1.1  christos 
    492  1.1  christos 
    493  1.1  christos /*-********************************************************
    494  1.1  christos * bitStream decoding
    495  1.1  christos **********************************************************/
    496  1.1  christos /*! BITv07_initDStream() :
    497  1.1  christos *   Initialize a BITv07_DStream_t.
    498  1.1  christos *   `bitD` : a pointer to an already allocated BITv07_DStream_t structure.
    499  1.1  christos *   `srcSize` must be the *exact* size of the bitStream, in bytes.
    500  1.1  christos *   @return : size of stream (== srcSize) or an errorCode if a problem is detected
    501  1.1  christos */
    502  1.1  christos MEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
    503  1.1  christos {
    504  1.1  christos     if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
    505  1.1  christos 
    506  1.1  christos     if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */
    507  1.1  christos         bitD->start = (const char*)srcBuffer;
    508  1.1  christos         bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
    509  1.1  christos         bitD->bitContainer = MEM_readLEST(bitD->ptr);
    510  1.1  christos         { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
    511  1.1  christos           bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;
    512  1.1  christos           if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
    513  1.1  christos     } else {
    514  1.1  christos         bitD->start = (const char*)srcBuffer;
    515  1.1  christos         bitD->ptr   = bitD->start;
    516  1.1  christos         bitD->bitContainer = *(const BYTE*)(bitD->start);
    517  1.1  christos         switch(srcSize)
    518  1.1  christos         {
    519  1.1  christos             case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */
    520  1.1  christos             case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */
    521  1.1  christos             case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */
    522  1.1  christos             case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */
    523  1.1  christos             case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */
    524  1.1  christos             case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8; /* fall-through */
    525  1.1  christos             default: break;
    526  1.1  christos         }
    527  1.1  christos         { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
    528  1.1  christos           bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;
    529  1.1  christos           if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
    530  1.1  christos         bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
    531  1.1  christos     }
    532  1.1  christos 
    533  1.1  christos     return srcSize;
    534  1.1  christos }
    535  1.1  christos 
    536  1.1  christos 
    537  1.1  christos  MEM_STATIC size_t BITv07_lookBits(const BITv07_DStream_t* bitD, U32 nbBits)
    538  1.1  christos {
    539  1.1  christos     U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
    540  1.1  christos     return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
    541  1.1  christos }
    542  1.1  christos 
    543  1.1  christos /*! BITv07_lookBitsFast() :
    544  1.1  christos *   unsafe version; only works if nbBits >= 1 */
    545  1.1  christos MEM_STATIC size_t BITv07_lookBitsFast(const BITv07_DStream_t* bitD, U32 nbBits)
    546  1.1  christos {
    547  1.1  christos     U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
    548  1.1  christos     return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
    549  1.1  christos }
    550  1.1  christos 
    551  1.1  christos MEM_STATIC void BITv07_skipBits(BITv07_DStream_t* bitD, U32 nbBits)
    552  1.1  christos {
    553  1.1  christos     bitD->bitsConsumed += nbBits;
    554  1.1  christos }
    555  1.1  christos 
    556  1.1  christos MEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, U32 nbBits)
    557  1.1  christos {
    558  1.1  christos     size_t const value = BITv07_lookBits(bitD, nbBits);
    559  1.1  christos     BITv07_skipBits(bitD, nbBits);
    560  1.1  christos     return value;
    561  1.1  christos }
    562  1.1  christos 
    563  1.1  christos /*! BITv07_readBitsFast() :
    564  1.1  christos *   unsafe version; only works if nbBits >= 1 */
    565  1.1  christos MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)
    566  1.1  christos {
    567  1.1  christos     size_t const value = BITv07_lookBitsFast(bitD, nbBits);
    568  1.1  christos     BITv07_skipBits(bitD, nbBits);
    569  1.1  christos     return value;
    570  1.1  christos }
    571  1.1  christos 
    572  1.1  christos MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)
    573  1.1  christos {
    574  1.1  christos     if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should not happen => corruption detected */
    575  1.1  christos         return BITv07_DStream_overflow;
    576  1.1  christos 
    577  1.1  christos     if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
    578  1.1  christos         bitD->ptr -= bitD->bitsConsumed >> 3;
    579  1.1  christos         bitD->bitsConsumed &= 7;
    580  1.1  christos         bitD->bitContainer = MEM_readLEST(bitD->ptr);
    581  1.1  christos         return BITv07_DStream_unfinished;
    582  1.1  christos     }
    583  1.1  christos     if (bitD->ptr == bitD->start) {
    584  1.1  christos         if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv07_DStream_endOfBuffer;
    585  1.1  christos         return BITv07_DStream_completed;
    586  1.1  christos     }
    587  1.1  christos     {   U32 nbBytes = bitD->bitsConsumed >> 3;
    588  1.1  christos         BITv07_DStream_status result = BITv07_DStream_unfinished;
    589  1.1  christos         if (bitD->ptr - nbBytes < bitD->start) {
    590  1.1  christos             nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */
    591  1.1  christos             result = BITv07_DStream_endOfBuffer;
    592  1.1  christos         }
    593  1.1  christos         bitD->ptr -= nbBytes;
    594  1.1  christos         bitD->bitsConsumed -= nbBytes*8;
    595  1.1  christos         bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */
    596  1.1  christos         return result;
    597  1.1  christos     }
    598  1.1  christos }
    599  1.1  christos 
    600  1.1  christos /*! BITv07_endOfDStream() :
    601  1.1  christos *   @return Tells if DStream has exactly reached its end (all bits consumed).
    602  1.1  christos */
    603  1.1  christos MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)
    604  1.1  christos {
    605  1.1  christos     return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
    606  1.1  christos }
    607  1.1  christos 
    608  1.1  christos #if defined (__cplusplus)
    609  1.1  christos }
    610  1.1  christos #endif
    611  1.1  christos 
    612  1.1  christos #endif /* BITSTREAM_H_MODULE */
    613  1.1  christos /* ******************************************************************
    614  1.1  christos    FSE : Finite State Entropy codec
    615  1.1  christos    Public Prototypes declaration
    616  1.1  christos    Copyright (C) 2013-2016, Yann Collet.
    617  1.1  christos 
    618  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
    619  1.1  christos 
    620  1.1  christos    Redistribution and use in source and binary forms, with or without
    621  1.1  christos    modification, are permitted provided that the following conditions are
    622  1.1  christos    met:
    623  1.1  christos 
    624  1.1  christos        * Redistributions of source code must retain the above copyright
    625  1.1  christos    notice, this list of conditions and the following disclaimer.
    626  1.1  christos        * Redistributions in binary form must reproduce the above
    627  1.1  christos    copyright notice, this list of conditions and the following disclaimer
    628  1.1  christos    in the documentation and/or other materials provided with the
    629  1.1  christos    distribution.
    630  1.1  christos 
    631  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    632  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    633  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    634  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    635  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    636  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    637  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    638  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    639  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    640  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    641  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    642  1.1  christos 
    643  1.1  christos    You can contact the author at :
    644  1.1  christos    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
    645  1.1  christos ****************************************************************** */
    646  1.1  christos #ifndef FSEv07_H
    647  1.1  christos #define FSEv07_H
    648  1.1  christos 
    649  1.1  christos #if defined (__cplusplus)
    650  1.1  christos extern "C" {
    651  1.1  christos #endif
    652  1.1  christos 
    653  1.1  christos 
    654  1.1  christos 
    655  1.1  christos /*-****************************************
    656  1.1  christos *  FSE simple functions
    657  1.1  christos ******************************************/
    658  1.1  christos 
    659  1.1  christos /*! FSEv07_decompress():
    660  1.1  christos     Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
    661  1.1  christos     into already allocated destination buffer 'dst', of size 'dstCapacity'.
    662  1.1  christos     @return : size of regenerated data (<= maxDstSize),
    663  1.1  christos               or an error code, which can be tested using FSEv07_isError() .
    664  1.1  christos 
    665  1.1  christos     ** Important ** : FSEv07_decompress() does not decompress non-compressible nor RLE data !!!
    666  1.1  christos     Why ? : making this distinction requires a header.
    667  1.1  christos     Header management is intentionally delegated to the user layer, which can better manage special cases.
    668  1.1  christos */
    669  1.1  christos size_t FSEv07_decompress(void* dst,  size_t dstCapacity,
    670  1.1  christos                 const void* cSrc, size_t cSrcSize);
    671  1.1  christos 
    672  1.1  christos 
    673  1.1  christos /* Error Management */
    674  1.1  christos unsigned    FSEv07_isError(size_t code);        /* tells if a return value is an error code */
    675  1.1  christos const char* FSEv07_getErrorName(size_t code);   /* provides error code string (useful for debugging) */
    676  1.1  christos 
    677  1.1  christos 
    678  1.1  christos /*-*****************************************
    679  1.1  christos *  FSE detailed API
    680  1.1  christos ******************************************/
    681  1.1  christos /*!
    682  1.1  christos FSEv07_decompress() does the following:
    683  1.1  christos 1. read normalized counters with readNCount()
    684  1.1  christos 2. build decoding table 'DTable' from normalized counters
    685  1.1  christos 3. decode the data stream using decoding table 'DTable'
    686  1.1  christos 
    687  1.1  christos The following API allows targeting specific sub-functions for advanced tasks.
    688  1.1  christos For example, it's possible to compress several blocks using the same 'CTable',
    689  1.1  christos or to save and provide normalized distribution using external method.
    690  1.1  christos */
    691  1.1  christos 
    692  1.1  christos 
    693  1.1  christos /* *** DECOMPRESSION *** */
    694  1.1  christos 
    695  1.1  christos /*! FSEv07_readNCount():
    696  1.1  christos     Read compactly saved 'normalizedCounter' from 'rBuffer'.
    697  1.1  christos     @return : size read from 'rBuffer',
    698  1.1  christos               or an errorCode, which can be tested using FSEv07_isError().
    699  1.1  christos               maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
    700  1.1  christos size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
    701  1.1  christos 
    702  1.1  christos /*! Constructor and Destructor of FSEv07_DTable.
    703  1.1  christos     Note that its size depends on 'tableLog' */
    704  1.1  christos typedef unsigned FSEv07_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
    705  1.1  christos FSEv07_DTable* FSEv07_createDTable(unsigned tableLog);
    706  1.1  christos void        FSEv07_freeDTable(FSEv07_DTable* dt);
    707  1.1  christos 
    708  1.1  christos /*! FSEv07_buildDTable():
    709  1.1  christos     Builds 'dt', which must be already allocated, using FSEv07_createDTable().
    710  1.1  christos     return : 0, or an errorCode, which can be tested using FSEv07_isError() */
    711  1.1  christos size_t FSEv07_buildDTable (FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
    712  1.1  christos 
    713  1.1  christos /*! FSEv07_decompress_usingDTable():
    714  1.1  christos     Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
    715  1.1  christos     into `dst` which must be already allocated.
    716  1.1  christos     @return : size of regenerated data (necessarily <= `dstCapacity`),
    717  1.1  christos               or an errorCode, which can be tested using FSEv07_isError() */
    718  1.1  christos size_t FSEv07_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv07_DTable* dt);
    719  1.1  christos 
    720  1.1  christos /*!
    721  1.1  christos Tutorial :
    722  1.1  christos ----------
    723  1.1  christos (Note : these functions only decompress FSE-compressed blocks.
    724  1.1  christos  If block is uncompressed, use memcpy() instead
    725  1.1  christos  If block is a single repeated byte, use memset() instead )
    726  1.1  christos 
    727  1.1  christos The first step is to obtain the normalized frequencies of symbols.
    728  1.1  christos This can be performed by FSEv07_readNCount() if it was saved using FSEv07_writeNCount().
    729  1.1  christos 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
    730  1.1  christos In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
    731  1.1  christos or size the table to handle worst case situations (typically 256).
    732  1.1  christos FSEv07_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
    733  1.1  christos The result of FSEv07_readNCount() is the number of bytes read from 'rBuffer'.
    734  1.1  christos Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
    735  1.1  christos If there is an error, the function will return an error code, which can be tested using FSEv07_isError().
    736  1.1  christos 
    737  1.1  christos The next step is to build the decompression tables 'FSEv07_DTable' from 'normalizedCounter'.
    738  1.1  christos This is performed by the function FSEv07_buildDTable().
    739  1.1  christos The space required by 'FSEv07_DTable' must be already allocated using FSEv07_createDTable().
    740  1.1  christos If there is an error, the function will return an error code, which can be tested using FSEv07_isError().
    741  1.1  christos 
    742  1.1  christos `FSEv07_DTable` can then be used to decompress `cSrc`, with FSEv07_decompress_usingDTable().
    743  1.1  christos `cSrcSize` must be strictly correct, otherwise decompression will fail.
    744  1.1  christos FSEv07_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
    745  1.1  christos If there is an error, the function will return an error code, which can be tested using FSEv07_isError(). (ex: dst buffer too small)
    746  1.1  christos */
    747  1.1  christos 
    748  1.1  christos 
    749  1.1  christos #ifdef FSEv07_STATIC_LINKING_ONLY
    750  1.1  christos 
    751  1.1  christos 
    752  1.1  christos /* *****************************************
    753  1.1  christos *  Static allocation
    754  1.1  christos *******************************************/
    755  1.1  christos /* FSE buffer bounds */
    756  1.1  christos #define FSEv07_NCOUNTBOUND 512
    757  1.1  christos #define FSEv07_BLOCKBOUND(size) (size + (size>>7))
    758  1.1  christos 
    759  1.1  christos /* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */
    760  1.1  christos #define FSEv07_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))
    761  1.1  christos 
    762  1.1  christos 
    763  1.1  christos /* *****************************************
    764  1.1  christos *  FSE advanced API
    765  1.1  christos *******************************************/
    766  1.1  christos size_t FSEv07_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
    767  1.1  christos /**< same as FSEv07_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr  */
    768  1.1  christos 
    769  1.1  christos unsigned FSEv07_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
    770  1.1  christos /**< same as FSEv07_optimalTableLog(), which used `minus==2` */
    771  1.1  christos 
    772  1.1  christos size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits);
    773  1.1  christos /**< build a fake FSEv07_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
    774  1.1  christos 
    775  1.1  christos size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, unsigned char symbolValue);
    776  1.1  christos /**< build a fake FSEv07_DTable, designed to always generate the same symbolValue */
    777  1.1  christos 
    778  1.1  christos 
    779  1.1  christos 
    780  1.1  christos /* *****************************************
    781  1.1  christos *  FSE symbol decompression API
    782  1.1  christos *******************************************/
    783  1.1  christos typedef struct
    784  1.1  christos {
    785  1.1  christos     size_t      state;
    786  1.1  christos     const void* table;   /* precise table may vary, depending on U16 */
    787  1.1  christos } FSEv07_DState_t;
    788  1.1  christos 
    789  1.1  christos 
    790  1.1  christos static void     FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt);
    791  1.1  christos 
    792  1.1  christos static unsigned char FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);
    793  1.1  christos 
    794  1.1  christos 
    795  1.1  christos 
    796  1.1  christos /* *****************************************
    797  1.1  christos *  FSE unsafe API
    798  1.1  christos *******************************************/
    799  1.1  christos static unsigned char FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);
    800  1.1  christos /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
    801  1.1  christos 
    802  1.1  christos 
    803  1.1  christos /* ======    Decompression    ====== */
    804  1.1  christos 
    805  1.1  christos typedef struct {
    806  1.1  christos     U16 tableLog;
    807  1.1  christos     U16 fastMode;
    808  1.1  christos } FSEv07_DTableHeader;   /* sizeof U32 */
    809  1.1  christos 
    810  1.1  christos typedef struct
    811  1.1  christos {
    812  1.1  christos     unsigned short newState;
    813  1.1  christos     unsigned char  symbol;
    814  1.1  christos     unsigned char  nbBits;
    815  1.1  christos } FSEv07_decode_t;   /* size == U32 */
    816  1.1  christos 
    817  1.1  christos MEM_STATIC void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt)
    818  1.1  christos {
    819  1.1  christos     const void* ptr = dt;
    820  1.1  christos     const FSEv07_DTableHeader* const DTableH = (const FSEv07_DTableHeader*)ptr;
    821  1.1  christos     DStatePtr->state = BITv07_readBits(bitD, DTableH->tableLog);
    822  1.1  christos     BITv07_reloadDStream(bitD);
    823  1.1  christos     DStatePtr->table = dt + 1;
    824  1.1  christos }
    825  1.1  christos 
    826  1.1  christos MEM_STATIC BYTE FSEv07_peekSymbol(const FSEv07_DState_t* DStatePtr)
    827  1.1  christos {
    828  1.1  christos     FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
    829  1.1  christos     return DInfo.symbol;
    830  1.1  christos }
    831  1.1  christos 
    832  1.1  christos MEM_STATIC void FSEv07_updateState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
    833  1.1  christos {
    834  1.1  christos     FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
    835  1.1  christos     U32 const nbBits = DInfo.nbBits;
    836  1.1  christos     size_t const lowBits = BITv07_readBits(bitD, nbBits);
    837  1.1  christos     DStatePtr->state = DInfo.newState + lowBits;
    838  1.1  christos }
    839  1.1  christos 
    840  1.1  christos MEM_STATIC BYTE FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
    841  1.1  christos {
    842  1.1  christos     FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
    843  1.1  christos     U32 const nbBits = DInfo.nbBits;
    844  1.1  christos     BYTE const symbol = DInfo.symbol;
    845  1.1  christos     size_t const lowBits = BITv07_readBits(bitD, nbBits);
    846  1.1  christos 
    847  1.1  christos     DStatePtr->state = DInfo.newState + lowBits;
    848  1.1  christos     return symbol;
    849  1.1  christos }
    850  1.1  christos 
    851  1.1  christos /*! FSEv07_decodeSymbolFast() :
    852  1.1  christos     unsafe, only works if no symbol has a probability > 50% */
    853  1.1  christos MEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)
    854  1.1  christos {
    855  1.1  christos     FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];
    856  1.1  christos     U32 const nbBits = DInfo.nbBits;
    857  1.1  christos     BYTE const symbol = DInfo.symbol;
    858  1.1  christos     size_t const lowBits = BITv07_readBitsFast(bitD, nbBits);
    859  1.1  christos 
    860  1.1  christos     DStatePtr->state = DInfo.newState + lowBits;
    861  1.1  christos     return symbol;
    862  1.1  christos }
    863  1.1  christos 
    864  1.1  christos 
    865  1.1  christos 
    866  1.1  christos #ifndef FSEv07_COMMONDEFS_ONLY
    867  1.1  christos 
    868  1.1  christos /* **************************************************************
    869  1.1  christos *  Tuning parameters
    870  1.1  christos ****************************************************************/
    871  1.1  christos /*!MEMORY_USAGE :
    872  1.1  christos *  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
    873  1.1  christos *  Increasing memory usage improves compression ratio
    874  1.1  christos *  Reduced memory usage can improve speed, due to cache effect
    875  1.1  christos *  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
    876  1.1  christos #define FSEv07_MAX_MEMORY_USAGE 14
    877  1.1  christos #define FSEv07_DEFAULT_MEMORY_USAGE 13
    878  1.1  christos 
    879  1.1  christos /*!FSEv07_MAX_SYMBOL_VALUE :
    880  1.1  christos *  Maximum symbol value authorized.
    881  1.1  christos *  Required for proper stack allocation */
    882  1.1  christos #define FSEv07_MAX_SYMBOL_VALUE 255
    883  1.1  christos 
    884  1.1  christos 
    885  1.1  christos /* **************************************************************
    886  1.1  christos *  template functions type & suffix
    887  1.1  christos ****************************************************************/
    888  1.1  christos #define FSEv07_FUNCTION_TYPE BYTE
    889  1.1  christos #define FSEv07_FUNCTION_EXTENSION
    890  1.1  christos #define FSEv07_DECODE_TYPE FSEv07_decode_t
    891  1.1  christos 
    892  1.1  christos 
    893  1.1  christos #endif   /* !FSEv07_COMMONDEFS_ONLY */
    894  1.1  christos 
    895  1.1  christos 
    896  1.1  christos /* ***************************************************************
    897  1.1  christos *  Constants
    898  1.1  christos *****************************************************************/
    899  1.1  christos #define FSEv07_MAX_TABLELOG  (FSEv07_MAX_MEMORY_USAGE-2)
    900  1.1  christos #define FSEv07_MAX_TABLESIZE (1U<<FSEv07_MAX_TABLELOG)
    901  1.1  christos #define FSEv07_MAXTABLESIZE_MASK (FSEv07_MAX_TABLESIZE-1)
    902  1.1  christos #define FSEv07_DEFAULT_TABLELOG (FSEv07_DEFAULT_MEMORY_USAGE-2)
    903  1.1  christos #define FSEv07_MIN_TABLELOG 5
    904  1.1  christos 
    905  1.1  christos #define FSEv07_TABLELOG_ABSOLUTE_MAX 15
    906  1.1  christos #if FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX
    907  1.1  christos #  error "FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX is not supported"
    908  1.1  christos #endif
    909  1.1  christos 
    910  1.1  christos #define FSEv07_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)
    911  1.1  christos 
    912  1.1  christos 
    913  1.1  christos #endif /* FSEv07_STATIC_LINKING_ONLY */
    914  1.1  christos 
    915  1.1  christos 
    916  1.1  christos #if defined (__cplusplus)
    917  1.1  christos }
    918  1.1  christos #endif
    919  1.1  christos 
    920  1.1  christos #endif  /* FSEv07_H */
    921  1.1  christos /* ******************************************************************
    922  1.1  christos    Huffman coder, part of New Generation Entropy library
    923  1.1  christos    header file
    924  1.1  christos    Copyright (C) 2013-2016, Yann Collet.
    925  1.1  christos 
    926  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
    927  1.1  christos 
    928  1.1  christos    Redistribution and use in source and binary forms, with or without
    929  1.1  christos    modification, are permitted provided that the following conditions are
    930  1.1  christos    met:
    931  1.1  christos 
    932  1.1  christos        * Redistributions of source code must retain the above copyright
    933  1.1  christos    notice, this list of conditions and the following disclaimer.
    934  1.1  christos        * Redistributions in binary form must reproduce the above
    935  1.1  christos    copyright notice, this list of conditions and the following disclaimer
    936  1.1  christos    in the documentation and/or other materials provided with the
    937  1.1  christos    distribution.
    938  1.1  christos 
    939  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    940  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    941  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    942  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    943  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    944  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    945  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    946  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    947  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    948  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    949  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    950  1.1  christos 
    951  1.1  christos    You can contact the author at :
    952  1.1  christos    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
    953  1.1  christos ****************************************************************** */
    954  1.1  christos #ifndef HUFv07_H_298734234
    955  1.1  christos #define HUFv07_H_298734234
    956  1.1  christos 
    957  1.1  christos #if defined (__cplusplus)
    958  1.1  christos extern "C" {
    959  1.1  christos #endif
    960  1.1  christos 
    961  1.1  christos 
    962  1.1  christos 
    963  1.1  christos /* *** simple functions *** */
    964  1.1  christos /**
    965  1.1  christos HUFv07_decompress() :
    966  1.1  christos     Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
    967  1.1  christos     into already allocated buffer 'dst', of minimum size 'dstSize'.
    968  1.1  christos     `dstSize` : **must** be the ***exact*** size of original (uncompressed) data.
    969  1.1  christos     Note : in contrast with FSE, HUFv07_decompress can regenerate
    970  1.1  christos            RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
    971  1.1  christos            because it knows size to regenerate.
    972  1.1  christos     @return : size of regenerated data (== dstSize),
    973  1.1  christos               or an error code, which can be tested using HUFv07_isError()
    974  1.1  christos */
    975  1.1  christos size_t HUFv07_decompress(void* dst,  size_t dstSize,
    976  1.1  christos                 const void* cSrc, size_t cSrcSize);
    977  1.1  christos 
    978  1.1  christos 
    979  1.1  christos /* ****************************************
    980  1.1  christos *  Tool functions
    981  1.1  christos ******************************************/
    982  1.1  christos #define HUFv07_BLOCKSIZE_MAX (128 * 1024)
    983  1.1  christos 
    984  1.1  christos /* Error Management */
    985  1.1  christos unsigned    HUFv07_isError(size_t code);        /**< tells if a return value is an error code */
    986  1.1  christos const char* HUFv07_getErrorName(size_t code);   /**< provides error code string (useful for debugging) */
    987  1.1  christos 
    988  1.1  christos 
    989  1.1  christos /* *** Advanced function *** */
    990  1.1  christos 
    991  1.1  christos 
    992  1.1  christos #ifdef HUFv07_STATIC_LINKING_ONLY
    993  1.1  christos 
    994  1.1  christos 
    995  1.1  christos /* *** Constants *** */
    996  1.1  christos #define HUFv07_TABLELOG_ABSOLUTEMAX  16   /* absolute limit of HUFv07_MAX_TABLELOG. Beyond that value, code does not work */
    997  1.1  christos #define HUFv07_TABLELOG_MAX  12           /* max configured tableLog (for static allocation); can be modified up to HUFv07_ABSOLUTEMAX_TABLELOG */
    998  1.1  christos #define HUFv07_TABLELOG_DEFAULT  11       /* tableLog by default, when not specified */
    999  1.1  christos #define HUFv07_SYMBOLVALUE_MAX 255
   1000  1.1  christos #if (HUFv07_TABLELOG_MAX > HUFv07_TABLELOG_ABSOLUTEMAX)
   1001  1.1  christos #  error "HUFv07_TABLELOG_MAX is too large !"
   1002  1.1  christos #endif
   1003  1.1  christos 
   1004  1.1  christos 
   1005  1.1  christos /* ****************************************
   1006  1.1  christos *  Static allocation
   1007  1.1  christos ******************************************/
   1008  1.1  christos /* HUF buffer bounds */
   1009  1.1  christos #define HUFv07_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */
   1010  1.1  christos 
   1011  1.1  christos /* static allocation of HUF's DTable */
   1012  1.1  christos typedef U32 HUFv07_DTable;
   1013  1.1  christos #define HUFv07_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))
   1014  1.1  christos #define HUFv07_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
   1015  1.1  christos         HUFv07_DTable DTable[HUFv07_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }
   1016  1.1  christos #define HUFv07_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
   1017  1.1  christos         HUFv07_DTable DTable[HUFv07_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }
   1018  1.1  christos 
   1019  1.1  christos 
   1020  1.1  christos /* ****************************************
   1021  1.1  christos *  Advanced decompression functions
   1022  1.1  christos ******************************************/
   1023  1.1  christos size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */
   1024  1.1  christos size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */
   1025  1.1  christos 
   1026  1.1  christos size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< decodes RLE and uncompressed */
   1027  1.1  christos size_t HUFv07_decompress4X_hufOnly(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
   1028  1.1  christos size_t HUFv07_decompress4X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */
   1029  1.1  christos size_t HUFv07_decompress4X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */
   1030  1.1  christos 
   1031  1.1  christos size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
   1032  1.1  christos size_t HUFv07_decompress1X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */
   1033  1.1  christos size_t HUFv07_decompress1X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */
   1034  1.1  christos 
   1035  1.1  christos 
   1036  1.1  christos /* ****************************************
   1037  1.1  christos *  HUF detailed API
   1038  1.1  christos ******************************************/
   1039  1.1  christos /*!
   1040  1.1  christos The following API allows targeting specific sub-functions for advanced tasks.
   1041  1.1  christos For example, it's possible to compress several blocks using the same 'CTable',
   1042  1.1  christos or to save and regenerate 'CTable' using external methods.
   1043  1.1  christos */
   1044  1.1  christos /* FSEv07_count() : find it within "fse.h" */
   1045  1.1  christos 
   1046  1.1  christos /*! HUFv07_readStats() :
   1047  1.1  christos     Read compact Huffman tree, saved by HUFv07_writeCTable().
   1048  1.1  christos     `huffWeight` is destination buffer.
   1049  1.1  christos     @return : size read from `src` , or an error Code .
   1050  1.1  christos     Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() . */
   1051  1.1  christos size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
   1052  1.1  christos                      U32* nbSymbolsPtr, U32* tableLogPtr,
   1053  1.1  christos                      const void* src, size_t srcSize);
   1054  1.1  christos 
   1055  1.1  christos 
   1056  1.1  christos /*
   1057  1.1  christos HUFv07_decompress() does the following:
   1058  1.1  christos 1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
   1059  1.1  christos 2. build Huffman table from save, using HUFv07_readDTableXn()
   1060  1.1  christos 3. decode 1 or 4 segments in parallel using HUFv07_decompressSXn_usingDTable
   1061  1.1  christos */
   1062  1.1  christos 
   1063  1.1  christos /** HUFv07_selectDecoder() :
   1064  1.1  christos *   Tells which decoder is likely to decode faster,
   1065  1.1  christos *   based on a set of pre-determined metrics.
   1066  1.1  christos *   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .
   1067  1.1  christos *   Assumption : 0 < cSrcSize < dstSize <= 128 KB */
   1068  1.1  christos U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize);
   1069  1.1  christos 
   1070  1.1  christos size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize);
   1071  1.1  christos size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize);
   1072  1.1  christos 
   1073  1.1  christos size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1074  1.1  christos size_t HUFv07_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1075  1.1  christos size_t HUFv07_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1076  1.1  christos 
   1077  1.1  christos 
   1078  1.1  christos /* single stream variants */
   1079  1.1  christos size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */
   1080  1.1  christos size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */
   1081  1.1  christos 
   1082  1.1  christos size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1083  1.1  christos size_t HUFv07_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1084  1.1  christos size_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);
   1085  1.1  christos 
   1086  1.1  christos 
   1087  1.1  christos #endif /* HUFv07_STATIC_LINKING_ONLY */
   1088  1.1  christos 
   1089  1.1  christos 
   1090  1.1  christos #if defined (__cplusplus)
   1091  1.1  christos }
   1092  1.1  christos #endif
   1093  1.1  christos 
   1094  1.1  christos #endif   /* HUFv07_H_298734234 */
   1095  1.1  christos /*
   1096  1.1  christos    Common functions of New Generation Entropy library
   1097  1.1  christos    Copyright (C) 2016, Yann Collet.
   1098  1.1  christos 
   1099  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   1100  1.1  christos 
   1101  1.1  christos    Redistribution and use in source and binary forms, with or without
   1102  1.1  christos    modification, are permitted provided that the following conditions are
   1103  1.1  christos    met:
   1104  1.1  christos 
   1105  1.1  christos        * Redistributions of source code must retain the above copyright
   1106  1.1  christos    notice, this list of conditions and the following disclaimer.
   1107  1.1  christos        * Redistributions in binary form must reproduce the above
   1108  1.1  christos    copyright notice, this list of conditions and the following disclaimer
   1109  1.1  christos    in the documentation and/or other materials provided with the
   1110  1.1  christos    distribution.
   1111  1.1  christos 
   1112  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   1113  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   1114  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   1115  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   1116  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   1117  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   1118  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1119  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1120  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1121  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   1122  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1123  1.1  christos 
   1124  1.1  christos     You can contact the author at :
   1125  1.1  christos     - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
   1126  1.1  christos     - Public forum : https://groups.google.com/forum/#!forum/lz4c
   1127  1.1  christos *************************************************************************** */
   1128  1.1  christos 
   1129  1.1  christos 
   1130  1.1  christos 
   1131  1.1  christos /*-****************************************
   1132  1.1  christos *  FSE Error Management
   1133  1.1  christos ******************************************/
   1134  1.1  christos unsigned FSEv07_isError(size_t code) { return ERR_isError(code); }
   1135  1.1  christos 
   1136  1.1  christos const char* FSEv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
   1137  1.1  christos 
   1138  1.1  christos 
   1139  1.1  christos /* **************************************************************
   1140  1.1  christos *  HUF Error Management
   1141  1.1  christos ****************************************************************/
   1142  1.1  christos unsigned HUFv07_isError(size_t code) { return ERR_isError(code); }
   1143  1.1  christos 
   1144  1.1  christos const char* HUFv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
   1145  1.1  christos 
   1146  1.1  christos 
   1147  1.1  christos /*-**************************************************************
   1148  1.1  christos *  FSE NCount encoding-decoding
   1149  1.1  christos ****************************************************************/
   1150  1.1  christos static short FSEv07_abs(short a) { return (short)(a<0 ? -a : a); }
   1151  1.1  christos 
   1152  1.1  christos size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
   1153  1.1  christos                  const void* headerBuffer, size_t hbSize)
   1154  1.1  christos {
   1155  1.1  christos     const BYTE* const istart = (const BYTE*) headerBuffer;
   1156  1.1  christos     const BYTE* const iend = istart + hbSize;
   1157  1.1  christos     const BYTE* ip = istart;
   1158  1.1  christos     int nbBits;
   1159  1.1  christos     int remaining;
   1160  1.1  christos     int threshold;
   1161  1.1  christos     U32 bitStream;
   1162  1.1  christos     int bitCount;
   1163  1.1  christos     unsigned charnum = 0;
   1164  1.1  christos     int previous0 = 0;
   1165  1.1  christos 
   1166  1.1  christos     if (hbSize < 4) return ERROR(srcSize_wrong);
   1167  1.1  christos     bitStream = MEM_readLE32(ip);
   1168  1.1  christos     nbBits = (bitStream & 0xF) + FSEv07_MIN_TABLELOG;   /* extract tableLog */
   1169  1.1  christos     if (nbBits > FSEv07_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
   1170  1.1  christos     bitStream >>= 4;
   1171  1.1  christos     bitCount = 4;
   1172  1.1  christos     *tableLogPtr = nbBits;
   1173  1.1  christos     remaining = (1<<nbBits)+1;
   1174  1.1  christos     threshold = 1<<nbBits;
   1175  1.1  christos     nbBits++;
   1176  1.1  christos 
   1177  1.1  christos     while ((remaining>1) && (charnum<=*maxSVPtr)) {
   1178  1.1  christos         if (previous0) {
   1179  1.1  christos             unsigned n0 = charnum;
   1180  1.1  christos             while ((bitStream & 0xFFFF) == 0xFFFF) {
   1181  1.1  christos                 n0+=24;
   1182  1.1  christos                 if (ip < iend-5) {
   1183  1.1  christos                     ip+=2;
   1184  1.1  christos                     bitStream = MEM_readLE32(ip) >> bitCount;
   1185  1.1  christos                 } else {
   1186  1.1  christos                     bitStream >>= 16;
   1187  1.1  christos                     bitCount+=16;
   1188  1.1  christos             }   }
   1189  1.1  christos             while ((bitStream & 3) == 3) {
   1190  1.1  christos                 n0+=3;
   1191  1.1  christos                 bitStream>>=2;
   1192  1.1  christos                 bitCount+=2;
   1193  1.1  christos             }
   1194  1.1  christos             n0 += bitStream & 3;
   1195  1.1  christos             bitCount += 2;
   1196  1.1  christos             if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
   1197  1.1  christos             while (charnum < n0) normalizedCounter[charnum++] = 0;
   1198  1.1  christos             if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
   1199  1.1  christos                 ip += bitCount>>3;
   1200  1.1  christos                 bitCount &= 7;
   1201  1.1  christos                 bitStream = MEM_readLE32(ip) >> bitCount;
   1202  1.1  christos             }
   1203  1.1  christos             else
   1204  1.1  christos                 bitStream >>= 2;
   1205  1.1  christos         }
   1206  1.1  christos         {   short const max = (short)((2*threshold-1)-remaining);
   1207  1.1  christos             short count;
   1208  1.1  christos 
   1209  1.1  christos             if ((bitStream & (threshold-1)) < (U32)max) {
   1210  1.1  christos                 count = (short)(bitStream & (threshold-1));
   1211  1.1  christos                 bitCount   += nbBits-1;
   1212  1.1  christos             } else {
   1213  1.1  christos                 count = (short)(bitStream & (2*threshold-1));
   1214  1.1  christos                 if (count >= threshold) count -= max;
   1215  1.1  christos                 bitCount   += nbBits;
   1216  1.1  christos             }
   1217  1.1  christos 
   1218  1.1  christos             count--;   /* extra accuracy */
   1219  1.1  christos             remaining -= FSEv07_abs(count);
   1220  1.1  christos             normalizedCounter[charnum++] = count;
   1221  1.1  christos             previous0 = !count;
   1222  1.1  christos             while (remaining < threshold) {
   1223  1.1  christos                 nbBits--;
   1224  1.1  christos                 threshold >>= 1;
   1225  1.1  christos             }
   1226  1.1  christos 
   1227  1.1  christos             if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
   1228  1.1  christos                 ip += bitCount>>3;
   1229  1.1  christos                 bitCount &= 7;
   1230  1.1  christos             } else {
   1231  1.1  christos                 bitCount -= (int)(8 * (iend - 4 - ip));
   1232  1.1  christos                 ip = iend - 4;
   1233  1.1  christos             }
   1234  1.1  christos             bitStream = MEM_readLE32(ip) >> (bitCount & 31);
   1235  1.1  christos     }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */
   1236  1.1  christos     if (remaining != 1) return ERROR(GENERIC);
   1237  1.1  christos     *maxSVPtr = charnum-1;
   1238  1.1  christos 
   1239  1.1  christos     ip += (bitCount+7)>>3;
   1240  1.1  christos     if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
   1241  1.1  christos     return ip-istart;
   1242  1.1  christos }
   1243  1.1  christos 
   1244  1.1  christos 
   1245  1.1  christos /*! HUFv07_readStats() :
   1246  1.1  christos     Read compact Huffman tree, saved by HUFv07_writeCTable().
   1247  1.1  christos     `huffWeight` is destination buffer.
   1248  1.1  christos     @return : size read from `src` , or an error Code .
   1249  1.1  christos     Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() .
   1250  1.1  christos */
   1251  1.1  christos size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
   1252  1.1  christos                      U32* nbSymbolsPtr, U32* tableLogPtr,
   1253  1.1  christos                      const void* src, size_t srcSize)
   1254  1.1  christos {
   1255  1.1  christos     U32 weightTotal;
   1256  1.1  christos     const BYTE* ip = (const BYTE*) src;
   1257  1.1  christos     size_t iSize;
   1258  1.1  christos     size_t oSize;
   1259  1.1  christos 
   1260  1.1  christos     if (!srcSize) return ERROR(srcSize_wrong);
   1261  1.1  christos     iSize = ip[0];
   1262  1.1  christos     /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */
   1263  1.1  christos 
   1264  1.1  christos     if (iSize >= 128)  { /* special header */
   1265  1.1  christos         if (iSize >= (242)) {  /* RLE */
   1266  1.1  christos             static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
   1267  1.1  christos             oSize = l[iSize-242];
   1268  1.1  christos             memset(huffWeight, 1, hwSize);
   1269  1.1  christos             iSize = 0;
   1270  1.1  christos         }
   1271  1.1  christos         else {   /* Incompressible */
   1272  1.1  christos             oSize = iSize - 127;
   1273  1.1  christos             iSize = ((oSize+1)/2);
   1274  1.1  christos             if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
   1275  1.1  christos             if (oSize >= hwSize) return ERROR(corruption_detected);
   1276  1.1  christos             ip += 1;
   1277  1.1  christos             {   U32 n;
   1278  1.1  christos                 for (n=0; n<oSize; n+=2) {
   1279  1.1  christos                     huffWeight[n]   = ip[n/2] >> 4;
   1280  1.1  christos                     huffWeight[n+1] = ip[n/2] & 15;
   1281  1.1  christos     }   }   }   }
   1282  1.1  christos     else  {   /* header compressed with FSE (normal case) */
   1283  1.1  christos         if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
   1284  1.1  christos         oSize = FSEv07_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */
   1285  1.1  christos         if (FSEv07_isError(oSize)) return oSize;
   1286  1.1  christos     }
   1287  1.1  christos 
   1288  1.1  christos     /* collect weight stats */
   1289  1.1  christos     memset(rankStats, 0, (HUFv07_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));
   1290  1.1  christos     weightTotal = 0;
   1291  1.1  christos     {   U32 n; for (n=0; n<oSize; n++) {
   1292  1.1  christos             if (huffWeight[n] >= HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
   1293  1.1  christos             rankStats[huffWeight[n]]++;
   1294  1.1  christos             weightTotal += (1 << huffWeight[n]) >> 1;
   1295  1.1  christos     }   }
   1296  1.1  christos     if (weightTotal == 0) return ERROR(corruption_detected);
   1297  1.1  christos 
   1298  1.1  christos     /* get last non-null symbol weight (implied, total must be 2^n) */
   1299  1.1  christos     {   U32 const tableLog = BITv07_highbit32(weightTotal) + 1;
   1300  1.1  christos         if (tableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
   1301  1.1  christos         *tableLogPtr = tableLog;
   1302  1.1  christos         /* determine last weight */
   1303  1.1  christos         {   U32 const total = 1 << tableLog;
   1304  1.1  christos             U32 const rest = total - weightTotal;
   1305  1.1  christos             U32 const verif = 1 << BITv07_highbit32(rest);
   1306  1.1  christos             U32 const lastWeight = BITv07_highbit32(rest) + 1;
   1307  1.1  christos             if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */
   1308  1.1  christos             huffWeight[oSize] = (BYTE)lastWeight;
   1309  1.1  christos             rankStats[lastWeight]++;
   1310  1.1  christos     }   }
   1311  1.1  christos 
   1312  1.1  christos     /* check tree construction validity */
   1313  1.1  christos     if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */
   1314  1.1  christos 
   1315  1.1  christos     /* results */
   1316  1.1  christos     *nbSymbolsPtr = (U32)(oSize+1);
   1317  1.1  christos     return iSize+1;
   1318  1.1  christos }
   1319  1.1  christos /* ******************************************************************
   1320  1.1  christos    FSE : Finite State Entropy decoder
   1321  1.1  christos    Copyright (C) 2013-2015, Yann Collet.
   1322  1.1  christos 
   1323  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   1324  1.1  christos 
   1325  1.1  christos    Redistribution and use in source and binary forms, with or without
   1326  1.1  christos    modification, are permitted provided that the following conditions are
   1327  1.1  christos    met:
   1328  1.1  christos 
   1329  1.1  christos        * Redistributions of source code must retain the above copyright
   1330  1.1  christos    notice, this list of conditions and the following disclaimer.
   1331  1.1  christos        * Redistributions in binary form must reproduce the above
   1332  1.1  christos    copyright notice, this list of conditions and the following disclaimer
   1333  1.1  christos    in the documentation and/or other materials provided with the
   1334  1.1  christos    distribution.
   1335  1.1  christos 
   1336  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   1337  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   1338  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   1339  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   1340  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   1341  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   1342  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1343  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1344  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1345  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   1346  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1347  1.1  christos 
   1348  1.1  christos     You can contact the author at :
   1349  1.1  christos     - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
   1350  1.1  christos     - Public forum : https://groups.google.com/forum/#!forum/lz4c
   1351  1.1  christos ****************************************************************** */
   1352  1.1  christos 
   1353  1.1  christos 
   1354  1.1  christos /* **************************************************************
   1355  1.1  christos *  Compiler specifics
   1356  1.1  christos ****************************************************************/
   1357  1.1  christos #ifdef _MSC_VER    /* Visual Studio */
   1358  1.1  christos #  define FORCE_INLINE static __forceinline
   1359  1.1  christos #  include <intrin.h>                    /* For Visual 2005 */
   1360  1.1  christos #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
   1361  1.1  christos #  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */
   1362  1.1  christos #else
   1363  1.1  christos #  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
   1364  1.1  christos #    ifdef __GNUC__
   1365  1.1  christos #      define FORCE_INLINE static inline __attribute__((always_inline))
   1366  1.1  christos #    else
   1367  1.1  christos #      define FORCE_INLINE static inline
   1368  1.1  christos #    endif
   1369  1.1  christos #  else
   1370  1.1  christos #    define FORCE_INLINE static
   1371  1.1  christos #  endif /* __STDC_VERSION__ */
   1372  1.1  christos #endif
   1373  1.1  christos 
   1374  1.1  christos 
   1375  1.1  christos /* **************************************************************
   1376  1.1  christos *  Error Management
   1377  1.1  christos ****************************************************************/
   1378  1.1  christos #define FSEv07_isError ERR_isError
   1379  1.1  christos #define FSEv07_STATIC_ASSERT(c) { enum { FSEv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
   1380  1.1  christos 
   1381  1.1  christos 
   1382  1.1  christos /* **************************************************************
   1383  1.1  christos *  Complex types
   1384  1.1  christos ****************************************************************/
   1385  1.1  christos typedef U32 DTable_max_t[FSEv07_DTABLE_SIZE_U32(FSEv07_MAX_TABLELOG)];
   1386  1.1  christos 
   1387  1.1  christos 
   1388  1.1  christos /* **************************************************************
   1389  1.1  christos *  Templates
   1390  1.1  christos ****************************************************************/
   1391  1.1  christos /*
   1392  1.1  christos   designed to be included
   1393  1.1  christos   for type-specific functions (template emulation in C)
   1394  1.1  christos   Objective is to write these functions only once, for improved maintenance
   1395  1.1  christos */
   1396  1.1  christos 
   1397  1.1  christos /* safety checks */
   1398  1.1  christos #ifndef FSEv07_FUNCTION_EXTENSION
   1399  1.1  christos #  error "FSEv07_FUNCTION_EXTENSION must be defined"
   1400  1.1  christos #endif
   1401  1.1  christos #ifndef FSEv07_FUNCTION_TYPE
   1402  1.1  christos #  error "FSEv07_FUNCTION_TYPE must be defined"
   1403  1.1  christos #endif
   1404  1.1  christos 
   1405  1.1  christos /* Function names */
   1406  1.1  christos #define FSEv07_CAT(X,Y) X##Y
   1407  1.1  christos #define FSEv07_FUNCTION_NAME(X,Y) FSEv07_CAT(X,Y)
   1408  1.1  christos #define FSEv07_TYPE_NAME(X,Y) FSEv07_CAT(X,Y)
   1409  1.1  christos 
   1410  1.1  christos 
   1411  1.1  christos /* Function templates */
   1412  1.1  christos FSEv07_DTable* FSEv07_createDTable (unsigned tableLog)
   1413  1.1  christos {
   1414  1.1  christos     if (tableLog > FSEv07_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv07_TABLELOG_ABSOLUTE_MAX;
   1415  1.1  christos     return (FSEv07_DTable*)malloc( FSEv07_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
   1416  1.1  christos }
   1417  1.1  christos 
   1418  1.1  christos void FSEv07_freeDTable (FSEv07_DTable* dt)
   1419  1.1  christos {
   1420  1.1  christos     free(dt);
   1421  1.1  christos }
   1422  1.1  christos 
   1423  1.1  christos size_t FSEv07_buildDTable(FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
   1424  1.1  christos {
   1425  1.1  christos     void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */
   1426  1.1  christos     FSEv07_DECODE_TYPE* const tableDecode = (FSEv07_DECODE_TYPE*) (tdPtr);
   1427  1.1  christos     U16 symbolNext[FSEv07_MAX_SYMBOL_VALUE+1];
   1428  1.1  christos 
   1429  1.1  christos     U32 const maxSV1 = maxSymbolValue + 1;
   1430  1.1  christos     U32 const tableSize = 1 << tableLog;
   1431  1.1  christos     U32 highThreshold = tableSize-1;
   1432  1.1  christos 
   1433  1.1  christos     /* Sanity Checks */
   1434  1.1  christos     if (maxSymbolValue > FSEv07_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
   1435  1.1  christos     if (tableLog > FSEv07_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
   1436  1.1  christos 
   1437  1.1  christos     /* Init, lay down lowprob symbols */
   1438  1.1  christos     {   FSEv07_DTableHeader DTableH;
   1439  1.1  christos         DTableH.tableLog = (U16)tableLog;
   1440  1.1  christos         DTableH.fastMode = 1;
   1441  1.1  christos         {   S16 const largeLimit= (S16)(1 << (tableLog-1));
   1442  1.1  christos             U32 s;
   1443  1.1  christos             for (s=0; s<maxSV1; s++) {
   1444  1.1  christos                 if (normalizedCounter[s]==-1) {
   1445  1.1  christos                     tableDecode[highThreshold--].symbol = (FSEv07_FUNCTION_TYPE)s;
   1446  1.1  christos                     symbolNext[s] = 1;
   1447  1.1  christos                 } else {
   1448  1.1  christos                     if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
   1449  1.1  christos                     symbolNext[s] = normalizedCounter[s];
   1450  1.1  christos         }   }   }
   1451  1.1  christos         memcpy(dt, &DTableH, sizeof(DTableH));
   1452  1.1  christos     }
   1453  1.1  christos 
   1454  1.1  christos     /* Spread symbols */
   1455  1.1  christos     {   U32 const tableMask = tableSize-1;
   1456  1.1  christos         U32 const step = FSEv07_TABLESTEP(tableSize);
   1457  1.1  christos         U32 s, position = 0;
   1458  1.1  christos         for (s=0; s<maxSV1; s++) {
   1459  1.1  christos             int i;
   1460  1.1  christos             for (i=0; i<normalizedCounter[s]; i++) {
   1461  1.1  christos                 tableDecode[position].symbol = (FSEv07_FUNCTION_TYPE)s;
   1462  1.1  christos                 position = (position + step) & tableMask;
   1463  1.1  christos                 while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */
   1464  1.1  christos         }   }
   1465  1.1  christos 
   1466  1.1  christos         if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */
   1467  1.1  christos     }
   1468  1.1  christos 
   1469  1.1  christos     /* Build Decoding table */
   1470  1.1  christos     {   U32 u;
   1471  1.1  christos         for (u=0; u<tableSize; u++) {
   1472  1.1  christos             FSEv07_FUNCTION_TYPE const symbol = (FSEv07_FUNCTION_TYPE)(tableDecode[u].symbol);
   1473  1.1  christos             U16 nextState = symbolNext[symbol]++;
   1474  1.1  christos             tableDecode[u].nbBits = (BYTE) (tableLog - BITv07_highbit32 ((U32)nextState) );
   1475  1.1  christos             tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
   1476  1.1  christos     }   }
   1477  1.1  christos 
   1478  1.1  christos     return 0;
   1479  1.1  christos }
   1480  1.1  christos 
   1481  1.1  christos 
   1482  1.1  christos 
   1483  1.1  christos #ifndef FSEv07_COMMONDEFS_ONLY
   1484  1.1  christos 
   1485  1.1  christos /*-*******************************************************
   1486  1.1  christos *  Decompression (Byte symbols)
   1487  1.1  christos *********************************************************/
   1488  1.1  christos size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, BYTE symbolValue)
   1489  1.1  christos {
   1490  1.1  christos     void* ptr = dt;
   1491  1.1  christos     FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;
   1492  1.1  christos     void* dPtr = dt + 1;
   1493  1.1  christos     FSEv07_decode_t* const cell = (FSEv07_decode_t*)dPtr;
   1494  1.1  christos 
   1495  1.1  christos     DTableH->tableLog = 0;
   1496  1.1  christos     DTableH->fastMode = 0;
   1497  1.1  christos 
   1498  1.1  christos     cell->newState = 0;
   1499  1.1  christos     cell->symbol = symbolValue;
   1500  1.1  christos     cell->nbBits = 0;
   1501  1.1  christos 
   1502  1.1  christos     return 0;
   1503  1.1  christos }
   1504  1.1  christos 
   1505  1.1  christos 
   1506  1.1  christos size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits)
   1507  1.1  christos {
   1508  1.1  christos     void* ptr = dt;
   1509  1.1  christos     FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;
   1510  1.1  christos     void* dPtr = dt + 1;
   1511  1.1  christos     FSEv07_decode_t* const dinfo = (FSEv07_decode_t*)dPtr;
   1512  1.1  christos     const unsigned tableSize = 1 << nbBits;
   1513  1.1  christos     const unsigned tableMask = tableSize - 1;
   1514  1.1  christos     const unsigned maxSV1 = tableMask+1;
   1515  1.1  christos     unsigned s;
   1516  1.1  christos 
   1517  1.1  christos     /* Sanity checks */
   1518  1.1  christos     if (nbBits < 1) return ERROR(GENERIC);         /* min size */
   1519  1.1  christos 
   1520  1.1  christos     /* Build Decoding Table */
   1521  1.1  christos     DTableH->tableLog = (U16)nbBits;
   1522  1.1  christos     DTableH->fastMode = 1;
   1523  1.1  christos     for (s=0; s<maxSV1; s++) {
   1524  1.1  christos         dinfo[s].newState = 0;
   1525  1.1  christos         dinfo[s].symbol = (BYTE)s;
   1526  1.1  christos         dinfo[s].nbBits = (BYTE)nbBits;
   1527  1.1  christos     }
   1528  1.1  christos 
   1529  1.1  christos     return 0;
   1530  1.1  christos }
   1531  1.1  christos 
   1532  1.1  christos FORCE_INLINE size_t FSEv07_decompress_usingDTable_generic(
   1533  1.1  christos           void* dst, size_t maxDstSize,
   1534  1.1  christos     const void* cSrc, size_t cSrcSize,
   1535  1.1  christos     const FSEv07_DTable* dt, const unsigned fast)
   1536  1.1  christos {
   1537  1.1  christos     BYTE* const ostart = (BYTE*) dst;
   1538  1.1  christos     BYTE* op = ostart;
   1539  1.1  christos     BYTE* const omax = op + maxDstSize;
   1540  1.1  christos     BYTE* const olimit = omax-3;
   1541  1.1  christos 
   1542  1.1  christos     BITv07_DStream_t bitD;
   1543  1.1  christos     FSEv07_DState_t state1;
   1544  1.1  christos     FSEv07_DState_t state2;
   1545  1.1  christos 
   1546  1.1  christos     /* Init */
   1547  1.1  christos     { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */
   1548  1.1  christos       if (FSEv07_isError(errorCode)) return errorCode; }
   1549  1.1  christos 
   1550  1.1  christos     FSEv07_initDState(&state1, &bitD, dt);
   1551  1.1  christos     FSEv07_initDState(&state2, &bitD, dt);
   1552  1.1  christos 
   1553  1.1  christos #define FSEv07_GETSYMBOL(statePtr) fast ? FSEv07_decodeSymbolFast(statePtr, &bitD) : FSEv07_decodeSymbol(statePtr, &bitD)
   1554  1.1  christos 
   1555  1.1  christos     /* 4 symbols per loop */
   1556  1.1  christos     for ( ; (BITv07_reloadDStream(&bitD)==BITv07_DStream_unfinished) && (op<olimit) ; op+=4) {
   1557  1.1  christos         op[0] = FSEv07_GETSYMBOL(&state1);
   1558  1.1  christos 
   1559  1.1  christos         if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
   1560  1.1  christos             BITv07_reloadDStream(&bitD);
   1561  1.1  christos 
   1562  1.1  christos         op[1] = FSEv07_GETSYMBOL(&state2);
   1563  1.1  christos 
   1564  1.1  christos         if (FSEv07_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
   1565  1.1  christos             { if (BITv07_reloadDStream(&bitD) > BITv07_DStream_unfinished) { op+=2; break; } }
   1566  1.1  christos 
   1567  1.1  christos         op[2] = FSEv07_GETSYMBOL(&state1);
   1568  1.1  christos 
   1569  1.1  christos         if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
   1570  1.1  christos             BITv07_reloadDStream(&bitD);
   1571  1.1  christos 
   1572  1.1  christos         op[3] = FSEv07_GETSYMBOL(&state2);
   1573  1.1  christos     }
   1574  1.1  christos 
   1575  1.1  christos     /* tail */
   1576  1.1  christos     /* note : BITv07_reloadDStream(&bitD) >= FSEv07_DStream_partiallyFilled; Ends at exactly BITv07_DStream_completed */
   1577  1.1  christos     while (1) {
   1578  1.1  christos         if (op>(omax-2)) return ERROR(dstSize_tooSmall);
   1579  1.1  christos 
   1580  1.1  christos         *op++ = FSEv07_GETSYMBOL(&state1);
   1581  1.1  christos 
   1582  1.1  christos         if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {
   1583  1.1  christos             *op++ = FSEv07_GETSYMBOL(&state2);
   1584  1.1  christos             break;
   1585  1.1  christos         }
   1586  1.1  christos 
   1587  1.1  christos         if (op>(omax-2)) return ERROR(dstSize_tooSmall);
   1588  1.1  christos 
   1589  1.1  christos         *op++ = FSEv07_GETSYMBOL(&state2);
   1590  1.1  christos 
   1591  1.1  christos         if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {
   1592  1.1  christos             *op++ = FSEv07_GETSYMBOL(&state1);
   1593  1.1  christos             break;
   1594  1.1  christos     }   }
   1595  1.1  christos 
   1596  1.1  christos     return op-ostart;
   1597  1.1  christos }
   1598  1.1  christos 
   1599  1.1  christos 
   1600  1.1  christos size_t FSEv07_decompress_usingDTable(void* dst, size_t originalSize,
   1601  1.1  christos                             const void* cSrc, size_t cSrcSize,
   1602  1.1  christos                             const FSEv07_DTable* dt)
   1603  1.1  christos {
   1604  1.1  christos     const void* ptr = dt;
   1605  1.1  christos     const FSEv07_DTableHeader* DTableH = (const FSEv07_DTableHeader*)ptr;
   1606  1.1  christos     const U32 fastMode = DTableH->fastMode;
   1607  1.1  christos 
   1608  1.1  christos     /* select fast mode (static) */
   1609  1.1  christos     if (fastMode) return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
   1610  1.1  christos     return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
   1611  1.1  christos }
   1612  1.1  christos 
   1613  1.1  christos 
   1614  1.1  christos size_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
   1615  1.1  christos {
   1616  1.1  christos     const BYTE* const istart = (const BYTE*)cSrc;
   1617  1.1  christos     const BYTE* ip = istart;
   1618  1.1  christos     short counting[FSEv07_MAX_SYMBOL_VALUE+1];
   1619  1.1  christos     DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */
   1620  1.1  christos     unsigned tableLog;
   1621  1.1  christos     unsigned maxSymbolValue = FSEv07_MAX_SYMBOL_VALUE;
   1622  1.1  christos 
   1623  1.1  christos     if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */
   1624  1.1  christos 
   1625  1.1  christos     /* normal FSE decoding mode */
   1626  1.1  christos     {   size_t const NCountLength = FSEv07_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
   1627  1.1  christos         if (FSEv07_isError(NCountLength)) return NCountLength;
   1628  1.1  christos         if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */
   1629  1.1  christos         ip += NCountLength;
   1630  1.1  christos         cSrcSize -= NCountLength;
   1631  1.1  christos     }
   1632  1.1  christos 
   1633  1.1  christos     { size_t const errorCode = FSEv07_buildDTable (dt, counting, maxSymbolValue, tableLog);
   1634  1.1  christos       if (FSEv07_isError(errorCode)) return errorCode; }
   1635  1.1  christos 
   1636  1.1  christos     return FSEv07_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */
   1637  1.1  christos }
   1638  1.1  christos 
   1639  1.1  christos 
   1640  1.1  christos 
   1641  1.1  christos #endif   /* FSEv07_COMMONDEFS_ONLY */
   1642  1.1  christos 
   1643  1.1  christos /* ******************************************************************
   1644  1.1  christos    Huffman decoder, part of New Generation Entropy library
   1645  1.1  christos    Copyright (C) 2013-2016, Yann Collet.
   1646  1.1  christos 
   1647  1.1  christos    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   1648  1.1  christos 
   1649  1.1  christos    Redistribution and use in source and binary forms, with or without
   1650  1.1  christos    modification, are permitted provided that the following conditions are
   1651  1.1  christos    met:
   1652  1.1  christos 
   1653  1.1  christos        * Redistributions of source code must retain the above copyright
   1654  1.1  christos    notice, this list of conditions and the following disclaimer.
   1655  1.1  christos        * Redistributions in binary form must reproduce the above
   1656  1.1  christos    copyright notice, this list of conditions and the following disclaimer
   1657  1.1  christos    in the documentation and/or other materials provided with the
   1658  1.1  christos    distribution.
   1659  1.1  christos 
   1660  1.1  christos    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   1661  1.1  christos    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   1662  1.1  christos    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   1663  1.1  christos    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   1664  1.1  christos    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   1665  1.1  christos    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   1666  1.1  christos    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1667  1.1  christos    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1668  1.1  christos    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1669  1.1  christos    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   1670  1.1  christos    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1671  1.1  christos 
   1672  1.1  christos     You can contact the author at :
   1673  1.1  christos     - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
   1674  1.1  christos     - Public forum : https://groups.google.com/forum/#!forum/lz4c
   1675  1.1  christos ****************************************************************** */
   1676  1.1  christos 
   1677  1.1  christos /* **************************************************************
   1678  1.1  christos *  Compiler specifics
   1679  1.1  christos ****************************************************************/
   1680  1.1  christos #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
   1681  1.1  christos /* inline is defined */
   1682  1.1  christos #elif defined(_MSC_VER)
   1683  1.1  christos #  define inline __inline
   1684  1.1  christos #else
   1685  1.1  christos #  define inline /* disable inline */
   1686  1.1  christos #endif
   1687  1.1  christos 
   1688  1.1  christos 
   1689  1.1  christos #ifdef _MSC_VER    /* Visual Studio */
   1690  1.1  christos #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
   1691  1.1  christos #endif
   1692  1.1  christos 
   1693  1.1  christos 
   1694  1.1  christos 
   1695  1.1  christos /* **************************************************************
   1696  1.1  christos *  Error Management
   1697  1.1  christos ****************************************************************/
   1698  1.1  christos #define HUFv07_STATIC_ASSERT(c) { enum { HUFv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
   1699  1.1  christos 
   1700  1.1  christos 
   1701  1.1  christos /*-***************************/
   1702  1.1  christos /*  generic DTableDesc       */
   1703  1.1  christos /*-***************************/
   1704  1.1  christos 
   1705  1.1  christos typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
   1706  1.1  christos 
   1707  1.1  christos static DTableDesc HUFv07_getDTableDesc(const HUFv07_DTable* table)
   1708  1.1  christos {
   1709  1.1  christos     DTableDesc dtd;
   1710  1.1  christos     memcpy(&dtd, table, sizeof(dtd));
   1711  1.1  christos     return dtd;
   1712  1.1  christos }
   1713  1.1  christos 
   1714  1.1  christos 
   1715  1.1  christos /*-***************************/
   1716  1.1  christos /*  single-symbol decoding   */
   1717  1.1  christos /*-***************************/
   1718  1.1  christos 
   1719  1.1  christos typedef struct { BYTE byte; BYTE nbBits; } HUFv07_DEltX2;   /* single-symbol decoding */
   1720  1.1  christos 
   1721  1.1  christos size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize)
   1722  1.1  christos {
   1723  1.1  christos     BYTE huffWeight[HUFv07_SYMBOLVALUE_MAX + 1];
   1724  1.1  christos     U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */
   1725  1.1  christos     U32 tableLog = 0;
   1726  1.1  christos     U32 nbSymbols = 0;
   1727  1.1  christos     size_t iSize;
   1728  1.1  christos     void* const dtPtr = DTable + 1;
   1729  1.1  christos     HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr;
   1730  1.1  christos 
   1731  1.1  christos     HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable));
   1732  1.1  christos     /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */
   1733  1.1  christos 
   1734  1.1  christos     iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
   1735  1.1  christos     if (HUFv07_isError(iSize)) return iSize;
   1736  1.1  christos 
   1737  1.1  christos     /* Table header */
   1738  1.1  christos     {   DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   1739  1.1  christos         if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, huffman tree cannot fit in */
   1740  1.1  christos         dtd.tableType = 0;
   1741  1.1  christos         dtd.tableLog = (BYTE)tableLog;
   1742  1.1  christos         memcpy(DTable, &dtd, sizeof(dtd));
   1743  1.1  christos     }
   1744  1.1  christos 
   1745  1.1  christos     /* Prepare ranks */
   1746  1.1  christos     {   U32 n, nextRankStart = 0;
   1747  1.1  christos         for (n=1; n<tableLog+1; n++) {
   1748  1.1  christos             U32 current = nextRankStart;
   1749  1.1  christos             nextRankStart += (rankVal[n] << (n-1));
   1750  1.1  christos             rankVal[n] = current;
   1751  1.1  christos     }   }
   1752  1.1  christos 
   1753  1.1  christos     /* fill DTable */
   1754  1.1  christos     {   U32 n;
   1755  1.1  christos         for (n=0; n<nbSymbols; n++) {
   1756  1.1  christos             U32 const w = huffWeight[n];
   1757  1.1  christos             U32 const length = (1 << w) >> 1;
   1758  1.1  christos             U32 i;
   1759  1.1  christos             HUFv07_DEltX2 D;
   1760  1.1  christos             D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
   1761  1.1  christos             for (i = rankVal[w]; i < rankVal[w] + length; i++)
   1762  1.1  christos                 dt[i] = D;
   1763  1.1  christos             rankVal[w] += length;
   1764  1.1  christos     }   }
   1765  1.1  christos 
   1766  1.1  christos     return iSize;
   1767  1.1  christos }
   1768  1.1  christos 
   1769  1.1  christos 
   1770  1.1  christos static BYTE HUFv07_decodeSymbolX2(BITv07_DStream_t* Dstream, const HUFv07_DEltX2* dt, const U32 dtLog)
   1771  1.1  christos {
   1772  1.1  christos     size_t const val = BITv07_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
   1773  1.1  christos     BYTE const c = dt[val].byte;
   1774  1.1  christos     BITv07_skipBits(Dstream, dt[val].nbBits);
   1775  1.1  christos     return c;
   1776  1.1  christos }
   1777  1.1  christos 
   1778  1.1  christos #define HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
   1779  1.1  christos     *ptr++ = HUFv07_decodeSymbolX2(DStreamPtr, dt, dtLog)
   1780  1.1  christos 
   1781  1.1  christos #define HUFv07_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
   1782  1.1  christos     if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \
   1783  1.1  christos         HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
   1784  1.1  christos 
   1785  1.1  christos #define HUFv07_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
   1786  1.1  christos     if (MEM_64bits()) \
   1787  1.1  christos         HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
   1788  1.1  christos 
   1789  1.1  christos static inline size_t HUFv07_decodeStreamX2(BYTE* p, BITv07_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv07_DEltX2* const dt, const U32 dtLog)
   1790  1.1  christos {
   1791  1.1  christos     BYTE* const pStart = p;
   1792  1.1  christos 
   1793  1.1  christos     /* up to 4 symbols at a time */
   1794  1.1  christos     while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-4)) {
   1795  1.1  christos         HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);
   1796  1.1  christos         HUFv07_DECODE_SYMBOLX2_1(p, bitDPtr);
   1797  1.1  christos         HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);
   1798  1.1  christos         HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
   1799  1.1  christos     }
   1800  1.1  christos 
   1801  1.1  christos     /* closer to the end */
   1802  1.1  christos     while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd))
   1803  1.1  christos         HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
   1804  1.1  christos 
   1805  1.1  christos     /* no more data to retrieve from bitstream, hence no need to reload */
   1806  1.1  christos     while (p < pEnd)
   1807  1.1  christos         HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);
   1808  1.1  christos 
   1809  1.1  christos     return pEnd-pStart;
   1810  1.1  christos }
   1811  1.1  christos 
   1812  1.1  christos static size_t HUFv07_decompress1X2_usingDTable_internal(
   1813  1.1  christos           void* dst,  size_t dstSize,
   1814  1.1  christos     const void* cSrc, size_t cSrcSize,
   1815  1.1  christos     const HUFv07_DTable* DTable)
   1816  1.1  christos {
   1817  1.1  christos     BYTE* op = (BYTE*)dst;
   1818  1.1  christos     BYTE* const oend = op + dstSize;
   1819  1.1  christos     const void* dtPtr = DTable + 1;
   1820  1.1  christos     const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;
   1821  1.1  christos     BITv07_DStream_t bitD;
   1822  1.1  christos     DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   1823  1.1  christos     U32 const dtLog = dtd.tableLog;
   1824  1.1  christos 
   1825  1.1  christos     { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);
   1826  1.1  christos       if (HUFv07_isError(errorCode)) return errorCode; }
   1827  1.1  christos 
   1828  1.1  christos     HUFv07_decodeStreamX2(op, &bitD, oend, dt, dtLog);
   1829  1.1  christos 
   1830  1.1  christos     /* check */
   1831  1.1  christos     if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);
   1832  1.1  christos 
   1833  1.1  christos     return dstSize;
   1834  1.1  christos }
   1835  1.1  christos 
   1836  1.1  christos size_t HUFv07_decompress1X2_usingDTable(
   1837  1.1  christos           void* dst,  size_t dstSize,
   1838  1.1  christos     const void* cSrc, size_t cSrcSize,
   1839  1.1  christos     const HUFv07_DTable* DTable)
   1840  1.1  christos {
   1841  1.1  christos     DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   1842  1.1  christos     if (dtd.tableType != 0) return ERROR(GENERIC);
   1843  1.1  christos     return HUFv07_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
   1844  1.1  christos }
   1845  1.1  christos 
   1846  1.1  christos size_t HUFv07_decompress1X2_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   1847  1.1  christos {
   1848  1.1  christos     const BYTE* ip = (const BYTE*) cSrc;
   1849  1.1  christos 
   1850  1.1  christos     size_t const hSize = HUFv07_readDTableX2 (DCtx, cSrc, cSrcSize);
   1851  1.1  christos     if (HUFv07_isError(hSize)) return hSize;
   1852  1.1  christos     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
   1853  1.1  christos     ip += hSize; cSrcSize -= hSize;
   1854  1.1  christos 
   1855  1.1  christos     return HUFv07_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
   1856  1.1  christos }
   1857  1.1  christos 
   1858  1.1  christos size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   1859  1.1  christos {
   1860  1.1  christos     HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);
   1861  1.1  christos     return HUFv07_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
   1862  1.1  christos }
   1863  1.1  christos 
   1864  1.1  christos 
   1865  1.1  christos static size_t HUFv07_decompress4X2_usingDTable_internal(
   1866  1.1  christos           void* dst,  size_t dstSize,
   1867  1.1  christos     const void* cSrc, size_t cSrcSize,
   1868  1.1  christos     const HUFv07_DTable* DTable)
   1869  1.1  christos {
   1870  1.1  christos     /* Check */
   1871  1.1  christos     if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */
   1872  1.1  christos 
   1873  1.1  christos     {   const BYTE* const istart = (const BYTE*) cSrc;
   1874  1.1  christos         BYTE* const ostart = (BYTE*) dst;
   1875  1.1  christos         BYTE* const oend = ostart + dstSize;
   1876  1.1  christos         const void* const dtPtr = DTable + 1;
   1877  1.1  christos         const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;
   1878  1.1  christos 
   1879  1.1  christos         /* Init */
   1880  1.1  christos         BITv07_DStream_t bitD1;
   1881  1.1  christos         BITv07_DStream_t bitD2;
   1882  1.1  christos         BITv07_DStream_t bitD3;
   1883  1.1  christos         BITv07_DStream_t bitD4;
   1884  1.1  christos         size_t const length1 = MEM_readLE16(istart);
   1885  1.1  christos         size_t const length2 = MEM_readLE16(istart+2);
   1886  1.1  christos         size_t const length3 = MEM_readLE16(istart+4);
   1887  1.1  christos         size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
   1888  1.1  christos         const BYTE* const istart1 = istart + 6;  /* jumpTable */
   1889  1.1  christos         const BYTE* const istart2 = istart1 + length1;
   1890  1.1  christos         const BYTE* const istart3 = istart2 + length2;
   1891  1.1  christos         const BYTE* const istart4 = istart3 + length3;
   1892  1.1  christos         const size_t segmentSize = (dstSize+3) / 4;
   1893  1.1  christos         BYTE* const opStart2 = ostart + segmentSize;
   1894  1.1  christos         BYTE* const opStart3 = opStart2 + segmentSize;
   1895  1.1  christos         BYTE* const opStart4 = opStart3 + segmentSize;
   1896  1.1  christos         BYTE* op1 = ostart;
   1897  1.1  christos         BYTE* op2 = opStart2;
   1898  1.1  christos         BYTE* op3 = opStart3;
   1899  1.1  christos         BYTE* op4 = opStart4;
   1900  1.1  christos         U32 endSignal;
   1901  1.1  christos         DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   1902  1.1  christos         U32 const dtLog = dtd.tableLog;
   1903  1.1  christos 
   1904  1.1  christos         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
   1905  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);
   1906  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   1907  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);
   1908  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   1909  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);
   1910  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   1911  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);
   1912  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   1913  1.1  christos 
   1914  1.1  christos         /* 16-32 symbols per loop (4-8 symbols per stream) */
   1915  1.1  christos         endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
   1916  1.1  christos         for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {
   1917  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);
   1918  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);
   1919  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);
   1920  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);
   1921  1.1  christos             HUFv07_DECODE_SYMBOLX2_1(op1, &bitD1);
   1922  1.1  christos             HUFv07_DECODE_SYMBOLX2_1(op2, &bitD2);
   1923  1.1  christos             HUFv07_DECODE_SYMBOLX2_1(op3, &bitD3);
   1924  1.1  christos             HUFv07_DECODE_SYMBOLX2_1(op4, &bitD4);
   1925  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);
   1926  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);
   1927  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);
   1928  1.1  christos             HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);
   1929  1.1  christos             HUFv07_DECODE_SYMBOLX2_0(op1, &bitD1);
   1930  1.1  christos             HUFv07_DECODE_SYMBOLX2_0(op2, &bitD2);
   1931  1.1  christos             HUFv07_DECODE_SYMBOLX2_0(op3, &bitD3);
   1932  1.1  christos             HUFv07_DECODE_SYMBOLX2_0(op4, &bitD4);
   1933  1.1  christos             endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
   1934  1.1  christos         }
   1935  1.1  christos 
   1936  1.1  christos         /* check corruption */
   1937  1.1  christos         if (op1 > opStart2) return ERROR(corruption_detected);
   1938  1.1  christos         if (op2 > opStart3) return ERROR(corruption_detected);
   1939  1.1  christos         if (op3 > opStart4) return ERROR(corruption_detected);
   1940  1.1  christos         /* note : op4 supposed already verified within main loop */
   1941  1.1  christos 
   1942  1.1  christos         /* finish bitStreams one by one */
   1943  1.1  christos         HUFv07_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
   1944  1.1  christos         HUFv07_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
   1945  1.1  christos         HUFv07_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
   1946  1.1  christos         HUFv07_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
   1947  1.1  christos 
   1948  1.1  christos         /* check */
   1949  1.1  christos         endSignal = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);
   1950  1.1  christos         if (!endSignal) return ERROR(corruption_detected);
   1951  1.1  christos 
   1952  1.1  christos         /* decoded size */
   1953  1.1  christos         return dstSize;
   1954  1.1  christos     }
   1955  1.1  christos }
   1956  1.1  christos 
   1957  1.1  christos 
   1958  1.1  christos size_t HUFv07_decompress4X2_usingDTable(
   1959  1.1  christos           void* dst,  size_t dstSize,
   1960  1.1  christos     const void* cSrc, size_t cSrcSize,
   1961  1.1  christos     const HUFv07_DTable* DTable)
   1962  1.1  christos {
   1963  1.1  christos     DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   1964  1.1  christos     if (dtd.tableType != 0) return ERROR(GENERIC);
   1965  1.1  christos     return HUFv07_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
   1966  1.1  christos }
   1967  1.1  christos 
   1968  1.1  christos 
   1969  1.1  christos size_t HUFv07_decompress4X2_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   1970  1.1  christos {
   1971  1.1  christos     const BYTE* ip = (const BYTE*) cSrc;
   1972  1.1  christos 
   1973  1.1  christos     size_t const hSize = HUFv07_readDTableX2 (dctx, cSrc, cSrcSize);
   1974  1.1  christos     if (HUFv07_isError(hSize)) return hSize;
   1975  1.1  christos     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
   1976  1.1  christos     ip += hSize; cSrcSize -= hSize;
   1977  1.1  christos 
   1978  1.1  christos     return HUFv07_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);
   1979  1.1  christos }
   1980  1.1  christos 
   1981  1.1  christos size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   1982  1.1  christos {
   1983  1.1  christos     HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);
   1984  1.1  christos     return HUFv07_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
   1985  1.1  christos }
   1986  1.1  christos 
   1987  1.1  christos 
   1988  1.1  christos /* *************************/
   1989  1.1  christos /* double-symbols decoding */
   1990  1.1  christos /* *************************/
   1991  1.1  christos typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv07_DEltX4;  /* double-symbols decoding */
   1992  1.1  christos 
   1993  1.1  christos typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
   1994  1.1  christos 
   1995  1.1  christos static void HUFv07_fillDTableX4Level2(HUFv07_DEltX4* DTable, U32 sizeLog, const U32 consumed,
   1996  1.1  christos                            const U32* rankValOrigin, const int minWeight,
   1997  1.1  christos                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
   1998  1.1  christos                            U32 nbBitsBaseline, U16 baseSeq)
   1999  1.1  christos {
   2000  1.1  christos     HUFv07_DEltX4 DElt;
   2001  1.1  christos     U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];
   2002  1.1  christos 
   2003  1.1  christos     /* get pre-calculated rankVal */
   2004  1.1  christos     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
   2005  1.1  christos 
   2006  1.1  christos     /* fill skipped values */
   2007  1.1  christos     if (minWeight>1) {
   2008  1.1  christos         U32 i, skipSize = rankVal[minWeight];
   2009  1.1  christos         MEM_writeLE16(&(DElt.sequence), baseSeq);
   2010  1.1  christos         DElt.nbBits   = (BYTE)(consumed);
   2011  1.1  christos         DElt.length   = 1;
   2012  1.1  christos         for (i = 0; i < skipSize; i++)
   2013  1.1  christos             DTable[i] = DElt;
   2014  1.1  christos     }
   2015  1.1  christos 
   2016  1.1  christos     /* fill DTable */
   2017  1.1  christos     { U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */
   2018  1.1  christos         const U32 symbol = sortedSymbols[s].symbol;
   2019  1.1  christos         const U32 weight = sortedSymbols[s].weight;
   2020  1.1  christos         const U32 nbBits = nbBitsBaseline - weight;
   2021  1.1  christos         const U32 length = 1 << (sizeLog-nbBits);
   2022  1.1  christos         const U32 start = rankVal[weight];
   2023  1.1  christos         U32 i = start;
   2024  1.1  christos         const U32 end = start + length;
   2025  1.1  christos 
   2026  1.1  christos         MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
   2027  1.1  christos         DElt.nbBits = (BYTE)(nbBits + consumed);
   2028  1.1  christos         DElt.length = 2;
   2029  1.1  christos         do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */
   2030  1.1  christos 
   2031  1.1  christos         rankVal[weight] += length;
   2032  1.1  christos     }}
   2033  1.1  christos }
   2034  1.1  christos 
   2035  1.1  christos typedef U32 rankVal_t[HUFv07_TABLELOG_ABSOLUTEMAX][HUFv07_TABLELOG_ABSOLUTEMAX + 1];
   2036  1.1  christos 
   2037  1.1  christos static void HUFv07_fillDTableX4(HUFv07_DEltX4* DTable, const U32 targetLog,
   2038  1.1  christos                            const sortedSymbol_t* sortedList, const U32 sortedListSize,
   2039  1.1  christos                            const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
   2040  1.1  christos                            const U32 nbBitsBaseline)
   2041  1.1  christos {
   2042  1.1  christos     U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];
   2043  1.1  christos     const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
   2044  1.1  christos     const U32 minBits  = nbBitsBaseline - maxWeight;
   2045  1.1  christos     U32 s;
   2046  1.1  christos 
   2047  1.1  christos     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
   2048  1.1  christos 
   2049  1.1  christos     /* fill DTable */
   2050  1.1  christos     for (s=0; s<sortedListSize; s++) {
   2051  1.1  christos         const U16 symbol = sortedList[s].symbol;
   2052  1.1  christos         const U32 weight = sortedList[s].weight;
   2053  1.1  christos         const U32 nbBits = nbBitsBaseline - weight;
   2054  1.1  christos         const U32 start = rankVal[weight];
   2055  1.1  christos         const U32 length = 1 << (targetLog-nbBits);
   2056  1.1  christos 
   2057  1.1  christos         if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */
   2058  1.1  christos             U32 sortedRank;
   2059  1.1  christos             int minWeight = nbBits + scaleLog;
   2060  1.1  christos             if (minWeight < 1) minWeight = 1;
   2061  1.1  christos             sortedRank = rankStart[minWeight];
   2062  1.1  christos             HUFv07_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
   2063  1.1  christos                            rankValOrigin[nbBits], minWeight,
   2064  1.1  christos                            sortedList+sortedRank, sortedListSize-sortedRank,
   2065  1.1  christos                            nbBitsBaseline, symbol);
   2066  1.1  christos         } else {
   2067  1.1  christos             HUFv07_DEltX4 DElt;
   2068  1.1  christos             MEM_writeLE16(&(DElt.sequence), symbol);
   2069  1.1  christos             DElt.nbBits = (BYTE)(nbBits);
   2070  1.1  christos             DElt.length = 1;
   2071  1.1  christos             {   U32 u;
   2072  1.1  christos                 const U32 end = start + length;
   2073  1.1  christos                 for (u = start; u < end; u++) DTable[u] = DElt;
   2074  1.1  christos         }   }
   2075  1.1  christos         rankVal[weight] += length;
   2076  1.1  christos     }
   2077  1.1  christos }
   2078  1.1  christos 
   2079  1.1  christos size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize)
   2080  1.1  christos {
   2081  1.1  christos     BYTE weightList[HUFv07_SYMBOLVALUE_MAX + 1];
   2082  1.1  christos     sortedSymbol_t sortedSymbol[HUFv07_SYMBOLVALUE_MAX + 1];
   2083  1.1  christos     U32 rankStats[HUFv07_TABLELOG_ABSOLUTEMAX + 1] = { 0 };
   2084  1.1  christos     U32 rankStart0[HUFv07_TABLELOG_ABSOLUTEMAX + 2] = { 0 };
   2085  1.1  christos     U32* const rankStart = rankStart0+1;
   2086  1.1  christos     rankVal_t rankVal;
   2087  1.1  christos     U32 tableLog, maxW, sizeOfSort, nbSymbols;
   2088  1.1  christos     DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   2089  1.1  christos     U32 const maxTableLog = dtd.maxTableLog;
   2090  1.1  christos     size_t iSize;
   2091  1.1  christos     void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */
   2092  1.1  christos     HUFv07_DEltX4* const dt = (HUFv07_DEltX4*)dtPtr;
   2093  1.1  christos 
   2094  1.1  christos     HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable));   /* if compilation fails here, assertion is false */
   2095  1.1  christos     if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);
   2096  1.1  christos     /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */
   2097  1.1  christos 
   2098  1.1  christos     iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
   2099  1.1  christos     if (HUFv07_isError(iSize)) return iSize;
   2100  1.1  christos 
   2101  1.1  christos     /* check result */
   2102  1.1  christos     if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
   2103  1.1  christos 
   2104  1.1  christos     /* find maxWeight */
   2105  1.1  christos     for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */
   2106  1.1  christos 
   2107  1.1  christos     /* Get start index of each weight */
   2108  1.1  christos     {   U32 w, nextRankStart = 0;
   2109  1.1  christos         for (w=1; w<maxW+1; w++) {
   2110  1.1  christos             U32 current = nextRankStart;
   2111  1.1  christos             nextRankStart += rankStats[w];
   2112  1.1  christos             rankStart[w] = current;
   2113  1.1  christos         }
   2114  1.1  christos         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
   2115  1.1  christos         sizeOfSort = nextRankStart;
   2116  1.1  christos     }
   2117  1.1  christos 
   2118  1.1  christos     /* sort symbols by weight */
   2119  1.1  christos     {   U32 s;
   2120  1.1  christos         for (s=0; s<nbSymbols; s++) {
   2121  1.1  christos             U32 const w = weightList[s];
   2122  1.1  christos             U32 const r = rankStart[w]++;
   2123  1.1  christos             sortedSymbol[r].symbol = (BYTE)s;
   2124  1.1  christos             sortedSymbol[r].weight = (BYTE)w;
   2125  1.1  christos         }
   2126  1.1  christos         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
   2127  1.1  christos     }
   2128  1.1  christos 
   2129  1.1  christos     /* Build rankVal */
   2130  1.1  christos     {   U32* const rankVal0 = rankVal[0];
   2131  1.1  christos         {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */
   2132  1.1  christos             U32 nextRankVal = 0;
   2133  1.1  christos             U32 w;
   2134  1.1  christos             for (w=1; w<maxW+1; w++) {
   2135  1.1  christos                 U32 current = nextRankVal;
   2136  1.1  christos                 nextRankVal += rankStats[w] << (w+rescale);
   2137  1.1  christos                 rankVal0[w] = current;
   2138  1.1  christos         }   }
   2139  1.1  christos         {   U32 const minBits = tableLog+1 - maxW;
   2140  1.1  christos             U32 consumed;
   2141  1.1  christos             for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
   2142  1.1  christos                 U32* const rankValPtr = rankVal[consumed];
   2143  1.1  christos                 U32 w;
   2144  1.1  christos                 for (w = 1; w < maxW+1; w++) {
   2145  1.1  christos                     rankValPtr[w] = rankVal0[w] >> consumed;
   2146  1.1  christos     }   }   }   }
   2147  1.1  christos 
   2148  1.1  christos     HUFv07_fillDTableX4(dt, maxTableLog,
   2149  1.1  christos                    sortedSymbol, sizeOfSort,
   2150  1.1  christos                    rankStart0, rankVal, maxW,
   2151  1.1  christos                    tableLog+1);
   2152  1.1  christos 
   2153  1.1  christos     dtd.tableLog = (BYTE)maxTableLog;
   2154  1.1  christos     dtd.tableType = 1;
   2155  1.1  christos     memcpy(DTable, &dtd, sizeof(dtd));
   2156  1.1  christos     return iSize;
   2157  1.1  christos }
   2158  1.1  christos 
   2159  1.1  christos 
   2160  1.1  christos static U32 HUFv07_decodeSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)
   2161  1.1  christos {
   2162  1.1  christos     const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
   2163  1.1  christos     memcpy(op, dt+val, 2);
   2164  1.1  christos     BITv07_skipBits(DStream, dt[val].nbBits);
   2165  1.1  christos     return dt[val].length;
   2166  1.1  christos }
   2167  1.1  christos 
   2168  1.1  christos static U32 HUFv07_decodeLastSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)
   2169  1.1  christos {
   2170  1.1  christos     const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
   2171  1.1  christos     memcpy(op, dt+val, 1);
   2172  1.1  christos     if (dt[val].length==1) BITv07_skipBits(DStream, dt[val].nbBits);
   2173  1.1  christos     else {
   2174  1.1  christos         if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
   2175  1.1  christos             BITv07_skipBits(DStream, dt[val].nbBits);
   2176  1.1  christos             if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
   2177  1.1  christos                 DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
   2178  1.1  christos     }   }
   2179  1.1  christos     return 1;
   2180  1.1  christos }
   2181  1.1  christos 
   2182  1.1  christos 
   2183  1.1  christos #define HUFv07_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
   2184  1.1  christos     ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
   2185  1.1  christos 
   2186  1.1  christos #define HUFv07_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
   2187  1.1  christos     if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \
   2188  1.1  christos         ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
   2189  1.1  christos 
   2190  1.1  christos #define HUFv07_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
   2191  1.1  christos     if (MEM_64bits()) \
   2192  1.1  christos         ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
   2193  1.1  christos 
   2194  1.1  christos static inline size_t HUFv07_decodeStreamX4(BYTE* p, BITv07_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv07_DEltX4* const dt, const U32 dtLog)
   2195  1.1  christos {
   2196  1.1  christos     BYTE* const pStart = p;
   2197  1.1  christos 
   2198  1.1  christos     /* up to 8 symbols at a time */
   2199  1.1  christos     while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd-7)) {
   2200  1.1  christos         HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);
   2201  1.1  christos         HUFv07_DECODE_SYMBOLX4_1(p, bitDPtr);
   2202  1.1  christos         HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);
   2203  1.1  christos         HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);
   2204  1.1  christos     }
   2205  1.1  christos 
   2206  1.1  christos     /* closer to end : up to 2 symbols at a time */
   2207  1.1  christos     while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-2))
   2208  1.1  christos         HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);
   2209  1.1  christos 
   2210  1.1  christos     while (p <= pEnd-2)
   2211  1.1  christos         HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
   2212  1.1  christos 
   2213  1.1  christos     if (p < pEnd)
   2214  1.1  christos         p += HUFv07_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
   2215  1.1  christos 
   2216  1.1  christos     return p-pStart;
   2217  1.1  christos }
   2218  1.1  christos 
   2219  1.1  christos 
   2220  1.1  christos static size_t HUFv07_decompress1X4_usingDTable_internal(
   2221  1.1  christos           void* dst,  size_t dstSize,
   2222  1.1  christos     const void* cSrc, size_t cSrcSize,
   2223  1.1  christos     const HUFv07_DTable* DTable)
   2224  1.1  christos {
   2225  1.1  christos     BITv07_DStream_t bitD;
   2226  1.1  christos 
   2227  1.1  christos     /* Init */
   2228  1.1  christos     {   size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);
   2229  1.1  christos         if (HUFv07_isError(errorCode)) return errorCode;
   2230  1.1  christos     }
   2231  1.1  christos 
   2232  1.1  christos     /* decode */
   2233  1.1  christos     {   BYTE* const ostart = (BYTE*) dst;
   2234  1.1  christos         BYTE* const oend = ostart + dstSize;
   2235  1.1  christos         const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */
   2236  1.1  christos         const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;
   2237  1.1  christos         DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   2238  1.1  christos         HUFv07_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
   2239  1.1  christos     }
   2240  1.1  christos 
   2241  1.1  christos     /* check */
   2242  1.1  christos     if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);
   2243  1.1  christos 
   2244  1.1  christos     /* decoded size */
   2245  1.1  christos     return dstSize;
   2246  1.1  christos }
   2247  1.1  christos 
   2248  1.1  christos size_t HUFv07_decompress1X4_usingDTable(
   2249  1.1  christos           void* dst,  size_t dstSize,
   2250  1.1  christos     const void* cSrc, size_t cSrcSize,
   2251  1.1  christos     const HUFv07_DTable* DTable)
   2252  1.1  christos {
   2253  1.1  christos     DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   2254  1.1  christos     if (dtd.tableType != 1) return ERROR(GENERIC);
   2255  1.1  christos     return HUFv07_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
   2256  1.1  christos }
   2257  1.1  christos 
   2258  1.1  christos size_t HUFv07_decompress1X4_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2259  1.1  christos {
   2260  1.1  christos     const BYTE* ip = (const BYTE*) cSrc;
   2261  1.1  christos 
   2262  1.1  christos     size_t const hSize = HUFv07_readDTableX4 (DCtx, cSrc, cSrcSize);
   2263  1.1  christos     if (HUFv07_isError(hSize)) return hSize;
   2264  1.1  christos     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
   2265  1.1  christos     ip += hSize; cSrcSize -= hSize;
   2266  1.1  christos 
   2267  1.1  christos     return HUFv07_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
   2268  1.1  christos }
   2269  1.1  christos 
   2270  1.1  christos size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2271  1.1  christos {
   2272  1.1  christos     HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);
   2273  1.1  christos     return HUFv07_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
   2274  1.1  christos }
   2275  1.1  christos 
   2276  1.1  christos static size_t HUFv07_decompress4X4_usingDTable_internal(
   2277  1.1  christos           void* dst,  size_t dstSize,
   2278  1.1  christos     const void* cSrc, size_t cSrcSize,
   2279  1.1  christos     const HUFv07_DTable* DTable)
   2280  1.1  christos {
   2281  1.1  christos     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
   2282  1.1  christos 
   2283  1.1  christos     {   const BYTE* const istart = (const BYTE*) cSrc;
   2284  1.1  christos         BYTE* const ostart = (BYTE*) dst;
   2285  1.1  christos         BYTE* const oend = ostart + dstSize;
   2286  1.1  christos         const void* const dtPtr = DTable+1;
   2287  1.1  christos         const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;
   2288  1.1  christos 
   2289  1.1  christos         /* Init */
   2290  1.1  christos         BITv07_DStream_t bitD1;
   2291  1.1  christos         BITv07_DStream_t bitD2;
   2292  1.1  christos         BITv07_DStream_t bitD3;
   2293  1.1  christos         BITv07_DStream_t bitD4;
   2294  1.1  christos         size_t const length1 = MEM_readLE16(istart);
   2295  1.1  christos         size_t const length2 = MEM_readLE16(istart+2);
   2296  1.1  christos         size_t const length3 = MEM_readLE16(istart+4);
   2297  1.1  christos         size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
   2298  1.1  christos         const BYTE* const istart1 = istart + 6;  /* jumpTable */
   2299  1.1  christos         const BYTE* const istart2 = istart1 + length1;
   2300  1.1  christos         const BYTE* const istart3 = istart2 + length2;
   2301  1.1  christos         const BYTE* const istart4 = istart3 + length3;
   2302  1.1  christos         size_t const segmentSize = (dstSize+3) / 4;
   2303  1.1  christos         BYTE* const opStart2 = ostart + segmentSize;
   2304  1.1  christos         BYTE* const opStart3 = opStart2 + segmentSize;
   2305  1.1  christos         BYTE* const opStart4 = opStart3 + segmentSize;
   2306  1.1  christos         BYTE* op1 = ostart;
   2307  1.1  christos         BYTE* op2 = opStart2;
   2308  1.1  christos         BYTE* op3 = opStart3;
   2309  1.1  christos         BYTE* op4 = opStart4;
   2310  1.1  christos         U32 endSignal;
   2311  1.1  christos         DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   2312  1.1  christos         U32 const dtLog = dtd.tableLog;
   2313  1.1  christos 
   2314  1.1  christos         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
   2315  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);
   2316  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   2317  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);
   2318  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   2319  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);
   2320  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   2321  1.1  christos         { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);
   2322  1.1  christos           if (HUFv07_isError(errorCode)) return errorCode; }
   2323  1.1  christos 
   2324  1.1  christos         /* 16-32 symbols per loop (4-8 symbols per stream) */
   2325  1.1  christos         endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
   2326  1.1  christos         for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {
   2327  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);
   2328  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);
   2329  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);
   2330  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);
   2331  1.1  christos             HUFv07_DECODE_SYMBOLX4_1(op1, &bitD1);
   2332  1.1  christos             HUFv07_DECODE_SYMBOLX4_1(op2, &bitD2);
   2333  1.1  christos             HUFv07_DECODE_SYMBOLX4_1(op3, &bitD3);
   2334  1.1  christos             HUFv07_DECODE_SYMBOLX4_1(op4, &bitD4);
   2335  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);
   2336  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);
   2337  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);
   2338  1.1  christos             HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);
   2339  1.1  christos             HUFv07_DECODE_SYMBOLX4_0(op1, &bitD1);
   2340  1.1  christos             HUFv07_DECODE_SYMBOLX4_0(op2, &bitD2);
   2341  1.1  christos             HUFv07_DECODE_SYMBOLX4_0(op3, &bitD3);
   2342  1.1  christos             HUFv07_DECODE_SYMBOLX4_0(op4, &bitD4);
   2343  1.1  christos 
   2344  1.1  christos             endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);
   2345  1.1  christos         }
   2346  1.1  christos 
   2347  1.1  christos         /* check corruption */
   2348  1.1  christos         if (op1 > opStart2) return ERROR(corruption_detected);
   2349  1.1  christos         if (op2 > opStart3) return ERROR(corruption_detected);
   2350  1.1  christos         if (op3 > opStart4) return ERROR(corruption_detected);
   2351  1.1  christos         /* note : op4 supposed already verified within main loop */
   2352  1.1  christos 
   2353  1.1  christos         /* finish bitStreams one by one */
   2354  1.1  christos         HUFv07_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
   2355  1.1  christos         HUFv07_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
   2356  1.1  christos         HUFv07_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
   2357  1.1  christos         HUFv07_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);
   2358  1.1  christos 
   2359  1.1  christos         /* check */
   2360  1.1  christos         { U32 const endCheck = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);
   2361  1.1  christos           if (!endCheck) return ERROR(corruption_detected); }
   2362  1.1  christos 
   2363  1.1  christos         /* decoded size */
   2364  1.1  christos         return dstSize;
   2365  1.1  christos     }
   2366  1.1  christos }
   2367  1.1  christos 
   2368  1.1  christos 
   2369  1.1  christos size_t HUFv07_decompress4X4_usingDTable(
   2370  1.1  christos           void* dst,  size_t dstSize,
   2371  1.1  christos     const void* cSrc, size_t cSrcSize,
   2372  1.1  christos     const HUFv07_DTable* DTable)
   2373  1.1  christos {
   2374  1.1  christos     DTableDesc dtd = HUFv07_getDTableDesc(DTable);
   2375  1.1  christos     if (dtd.tableType != 1) return ERROR(GENERIC);
   2376  1.1  christos     return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
   2377  1.1  christos }
   2378  1.1  christos 
   2379  1.1  christos 
   2380  1.1  christos size_t HUFv07_decompress4X4_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2381  1.1  christos {
   2382  1.1  christos     const BYTE* ip = (const BYTE*) cSrc;
   2383  1.1  christos 
   2384  1.1  christos     size_t hSize = HUFv07_readDTableX4 (dctx, cSrc, cSrcSize);
   2385  1.1  christos     if (HUFv07_isError(hSize)) return hSize;
   2386  1.1  christos     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
   2387  1.1  christos     ip += hSize; cSrcSize -= hSize;
   2388  1.1  christos 
   2389  1.1  christos     return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
   2390  1.1  christos }
   2391  1.1  christos 
   2392  1.1  christos size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2393  1.1  christos {
   2394  1.1  christos     HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);
   2395  1.1  christos     return HUFv07_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
   2396  1.1  christos }
   2397  1.1  christos 
   2398  1.1  christos 
   2399  1.1  christos /* ********************************/
   2400  1.1  christos /* Generic decompression selector */
   2401  1.1  christos /* ********************************/
   2402  1.1  christos 
   2403  1.1  christos size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize,
   2404  1.1  christos                                     const void* cSrc, size_t cSrcSize,
   2405  1.1  christos                                     const HUFv07_DTable* DTable)
   2406  1.1  christos {
   2407  1.1  christos     DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   2408  1.1  christos     return dtd.tableType ? HUFv07_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
   2409  1.1  christos                            HUFv07_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
   2410  1.1  christos }
   2411  1.1  christos 
   2412  1.1  christos size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize,
   2413  1.1  christos                                     const void* cSrc, size_t cSrcSize,
   2414  1.1  christos                                     const HUFv07_DTable* DTable)
   2415  1.1  christos {
   2416  1.1  christos     DTableDesc const dtd = HUFv07_getDTableDesc(DTable);
   2417  1.1  christos     return dtd.tableType ? HUFv07_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
   2418  1.1  christos                            HUFv07_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
   2419  1.1  christos }
   2420  1.1  christos 
   2421  1.1  christos 
   2422  1.1  christos typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
   2423  1.1  christos static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
   2424  1.1  christos {
   2425  1.1  christos     /* single, double, quad */
   2426  1.1  christos     {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */
   2427  1.1  christos     {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */
   2428  1.1  christos     {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */
   2429  1.1  christos     {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */
   2430  1.1  christos     {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */
   2431  1.1  christos     {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */
   2432  1.1  christos     {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */
   2433  1.1  christos     {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */
   2434  1.1  christos     {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */
   2435  1.1  christos     {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */
   2436  1.1  christos     {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */
   2437  1.1  christos     {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */
   2438  1.1  christos     {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */
   2439  1.1  christos     {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */
   2440  1.1  christos     {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */
   2441  1.1  christos     {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */
   2442  1.1  christos };
   2443  1.1  christos 
   2444  1.1  christos /** HUFv07_selectDecoder() :
   2445  1.1  christos *   Tells which decoder is likely to decode faster,
   2446  1.1  christos *   based on a set of pre-determined metrics.
   2447  1.1  christos *   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .
   2448  1.1  christos *   Assumption : 0 < cSrcSize < dstSize <= 128 KB */
   2449  1.1  christos U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize)
   2450  1.1  christos {
   2451  1.1  christos     /* decoder timing evaluation */
   2452  1.1  christos     U32 const Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */
   2453  1.1  christos     U32 const D256 = (U32)(dstSize >> 8);
   2454  1.1  christos     U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
   2455  1.1  christos     U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
   2456  1.1  christos     DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, for cache eviction */
   2457  1.1  christos 
   2458  1.1  christos     return DTime1 < DTime0;
   2459  1.1  christos }
   2460  1.1  christos 
   2461  1.1  christos 
   2462  1.1  christos typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
   2463  1.1  christos 
   2464  1.1  christos size_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2465  1.1  christos {
   2466  1.1  christos     static const decompressionAlgo decompress[2] = { HUFv07_decompress4X2, HUFv07_decompress4X4 };
   2467  1.1  christos 
   2468  1.1  christos     /* validation checks */
   2469  1.1  christos     if (dstSize == 0) return ERROR(dstSize_tooSmall);
   2470  1.1  christos     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
   2471  1.1  christos     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
   2472  1.1  christos     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
   2473  1.1  christos 
   2474  1.1  christos     {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
   2475  1.1  christos         return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
   2476  1.1  christos     }
   2477  1.1  christos 
   2478  1.1  christos     /* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */
   2479  1.1  christos     /* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */
   2480  1.1  christos }
   2481  1.1  christos 
   2482  1.1  christos size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2483  1.1  christos {
   2484  1.1  christos     /* validation checks */
   2485  1.1  christos     if (dstSize == 0) return ERROR(dstSize_tooSmall);
   2486  1.1  christos     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
   2487  1.1  christos     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
   2488  1.1  christos     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
   2489  1.1  christos 
   2490  1.1  christos     {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
   2491  1.1  christos         return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
   2492  1.1  christos                         HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
   2493  1.1  christos     }
   2494  1.1  christos }
   2495  1.1  christos 
   2496  1.1  christos size_t HUFv07_decompress4X_hufOnly (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2497  1.1  christos {
   2498  1.1  christos     /* validation checks */
   2499  1.1  christos     if (dstSize == 0) return ERROR(dstSize_tooSmall);
   2500  1.1  christos     if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected);   /* invalid */
   2501  1.1  christos 
   2502  1.1  christos     {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
   2503  1.1  christos         return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
   2504  1.1  christos                         HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
   2505  1.1  christos     }
   2506  1.1  christos }
   2507  1.1  christos 
   2508  1.1  christos size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
   2509  1.1  christos {
   2510  1.1  christos     /* validation checks */
   2511  1.1  christos     if (dstSize == 0) return ERROR(dstSize_tooSmall);
   2512  1.1  christos     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
   2513  1.1  christos     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
   2514  1.1  christos     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
   2515  1.1  christos 
   2516  1.1  christos     {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);
   2517  1.1  christos         return algoNb ? HUFv07_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
   2518  1.1  christos                         HUFv07_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
   2519  1.1  christos     }
   2520  1.1  christos }
   2521  1.1  christos /*
   2522  1.1  christos     Common functions of Zstd compression library
   2523  1.1  christos     Copyright (C) 2015-2016, Yann Collet.
   2524  1.1  christos 
   2525  1.1  christos     BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   2526  1.1  christos 
   2527  1.1  christos     Redistribution and use in source and binary forms, with or without
   2528  1.1  christos     modification, are permitted provided that the following conditions are
   2529  1.1  christos     met:
   2530  1.1  christos     * Redistributions of source code must retain the above copyright
   2531  1.1  christos     notice, this list of conditions and the following disclaimer.
   2532  1.1  christos     * Redistributions in binary form must reproduce the above
   2533  1.1  christos     copyright notice, this list of conditions and the following disclaimer
   2534  1.1  christos     in the documentation and/or other materials provided with the
   2535  1.1  christos     distribution.
   2536  1.1  christos     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   2537  1.1  christos     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   2538  1.1  christos     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   2539  1.1  christos     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   2540  1.1  christos     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   2541  1.1  christos     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   2542  1.1  christos     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   2543  1.1  christos     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   2544  1.1  christos     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   2545  1.1  christos     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   2546  1.1  christos     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   2547  1.1  christos 
   2548  1.1  christos     You can contact the author at :
   2549  1.1  christos     - zstd homepage : https://facebook.github.io/zstd/
   2550  1.1  christos */
   2551  1.1  christos 
   2552  1.1  christos 
   2553  1.1  christos 
   2554  1.1  christos /*-****************************************
   2555  1.1  christos *  ZSTD Error Management
   2556  1.1  christos ******************************************/
   2557  1.1  christos /*! ZSTDv07_isError() :
   2558  1.1  christos *   tells if a return value is an error code */
   2559  1.1  christos unsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }
   2560  1.1  christos 
   2561  1.1  christos /*! ZSTDv07_getErrorName() :
   2562  1.1  christos *   provides error code string from function result (useful for debugging) */
   2563  1.1  christos const char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }
   2564  1.1  christos 
   2565  1.1  christos 
   2566  1.1  christos 
   2567  1.1  christos /* **************************************************************
   2568  1.1  christos *  ZBUFF Error Management
   2569  1.1  christos ****************************************************************/
   2570  1.1  christos unsigned ZBUFFv07_isError(size_t errorCode) { return ERR_isError(errorCode); }
   2571  1.1  christos 
   2572  1.1  christos const char* ZBUFFv07_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
   2573  1.1  christos 
   2574  1.1  christos 
   2575  1.1  christos 
   2576  1.1  christos static void* ZSTDv07_defaultAllocFunction(void* opaque, size_t size)
   2577  1.1  christos {
   2578  1.1  christos     void* address = malloc(size);
   2579  1.1  christos     (void)opaque;
   2580  1.1  christos     /* printf("alloc %p, %d opaque=%p \n", address, (int)size, opaque); */
   2581  1.1  christos     return address;
   2582  1.1  christos }
   2583  1.1  christos 
   2584  1.1  christos static void ZSTDv07_defaultFreeFunction(void* opaque, void* address)
   2585  1.1  christos {
   2586  1.1  christos     (void)opaque;
   2587  1.1  christos     /* if (address) printf("free %p opaque=%p \n", address, opaque); */
   2588  1.1  christos     free(address);
   2589  1.1  christos }
   2590  1.1  christos /*
   2591  1.1  christos     zstd_internal - common functions to include
   2592  1.1  christos     Header File for include
   2593  1.1  christos     Copyright (C) 2014-2016, Yann Collet.
   2594  1.1  christos 
   2595  1.1  christos     BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   2596  1.1  christos 
   2597  1.1  christos     Redistribution and use in source and binary forms, with or without
   2598  1.1  christos     modification, are permitted provided that the following conditions are
   2599  1.1  christos     met:
   2600  1.1  christos     * Redistributions of source code must retain the above copyright
   2601  1.1  christos     notice, this list of conditions and the following disclaimer.
   2602  1.1  christos     * Redistributions in binary form must reproduce the above
   2603  1.1  christos     copyright notice, this list of conditions and the following disclaimer
   2604  1.1  christos     in the documentation and/or other materials provided with the
   2605  1.1  christos     distribution.
   2606  1.1  christos     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   2607  1.1  christos     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   2608  1.1  christos     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   2609  1.1  christos     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   2610  1.1  christos     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   2611  1.1  christos     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   2612  1.1  christos     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   2613  1.1  christos     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   2614  1.1  christos     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   2615  1.1  christos     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   2616  1.1  christos     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   2617  1.1  christos 
   2618  1.1  christos     You can contact the author at :
   2619  1.1  christos     - zstd homepage : https://www.zstd.net
   2620  1.1  christos */
   2621  1.1  christos #ifndef ZSTDv07_CCOMMON_H_MODULE
   2622  1.1  christos #define ZSTDv07_CCOMMON_H_MODULE
   2623  1.1  christos 
   2624  1.1  christos 
   2625  1.1  christos /*-*************************************
   2626  1.1  christos *  Common macros
   2627  1.1  christos ***************************************/
   2628  1.1  christos #define MIN(a,b) ((a)<(b) ? (a) : (b))
   2629  1.1  christos #define MAX(a,b) ((a)>(b) ? (a) : (b))
   2630  1.1  christos 
   2631  1.1  christos 
   2632  1.1  christos /*-*************************************
   2633  1.1  christos *  Common constants
   2634  1.1  christos ***************************************/
   2635  1.1  christos #define ZSTDv07_OPT_NUM    (1<<12)
   2636  1.1  christos #define ZSTDv07_DICT_MAGIC  0xEC30A437   /* v0.7 */
   2637  1.1  christos 
   2638  1.1  christos #define ZSTDv07_REP_NUM    3
   2639  1.1  christos #define ZSTDv07_REP_INIT   ZSTDv07_REP_NUM
   2640  1.1  christos #define ZSTDv07_REP_MOVE   (ZSTDv07_REP_NUM-1)
   2641  1.1  christos static const U32 repStartValue[ZSTDv07_REP_NUM] = { 1, 4, 8 };
   2642  1.1  christos 
   2643  1.1  christos #define KB *(1 <<10)
   2644  1.1  christos #define MB *(1 <<20)
   2645  1.1  christos #define GB *(1U<<30)
   2646  1.1  christos 
   2647  1.1  christos #define BIT7 128
   2648  1.1  christos #define BIT6  64
   2649  1.1  christos #define BIT5  32
   2650  1.1  christos #define BIT4  16
   2651  1.1  christos #define BIT1   2
   2652  1.1  christos #define BIT0   1
   2653  1.1  christos 
   2654  1.1  christos #define ZSTDv07_WINDOWLOG_ABSOLUTEMIN 10
   2655  1.1  christos static const size_t ZSTDv07_fcs_fieldSize[4] = { 0, 2, 4, 8 };
   2656  1.1  christos static const size_t ZSTDv07_did_fieldSize[4] = { 0, 1, 2, 4 };
   2657  1.1  christos 
   2658  1.1  christos #define ZSTDv07_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
   2659  1.1  christos static const size_t ZSTDv07_blockHeaderSize = ZSTDv07_BLOCKHEADERSIZE;
   2660  1.1  christos typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
   2661  1.1  christos 
   2662  1.1  christos #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
   2663  1.1  christos #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */
   2664  1.1  christos 
   2665  1.1  christos #define ZSTD_HUFFDTABLE_CAPACITY_LOG 12
   2666  1.1  christos typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;
   2667  1.1  christos 
   2668  1.1  christos #define LONGNBSEQ 0x7F00
   2669  1.1  christos 
   2670  1.1  christos #define MINMATCH 3
   2671  1.1  christos #define EQUAL_READ32 4
   2672  1.1  christos 
   2673  1.1  christos #define Litbits  8
   2674  1.1  christos #define MaxLit ((1<<Litbits) - 1)
   2675  1.1  christos #define MaxML  52
   2676  1.1  christos #define MaxLL  35
   2677  1.1  christos #define MaxOff 28
   2678  1.1  christos #define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */
   2679  1.1  christos #define MLFSELog    9
   2680  1.1  christos #define LLFSELog    9
   2681  1.1  christos #define OffFSELog   8
   2682  1.1  christos 
   2683  1.1  christos #define FSEv07_ENCODING_RAW     0
   2684  1.1  christos #define FSEv07_ENCODING_RLE     1
   2685  1.1  christos #define FSEv07_ENCODING_STATIC  2
   2686  1.1  christos #define FSEv07_ENCODING_DYNAMIC 3
   2687  1.1  christos 
   2688  1.1  christos #define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
   2689  1.1  christos 
   2690  1.1  christos static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   2691  1.1  christos                                       1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
   2692  1.1  christos                                      13,14,15,16 };
   2693  1.1  christos static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
   2694  1.1  christos                                              2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
   2695  1.1  christos                                             -1,-1,-1,-1 };
   2696  1.1  christos static const U32 LL_defaultNormLog = 6;
   2697  1.1  christos 
   2698  1.1  christos static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   2699  1.1  christos                                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   2700  1.1  christos                                       1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,
   2701  1.1  christos                                      12,13,14,15,16 };
   2702  1.1  christos static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
   2703  1.1  christos                                              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   2704  1.1  christos                                              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
   2705  1.1  christos                                             -1,-1,-1,-1,-1 };
   2706  1.1  christos static const U32 ML_defaultNormLog = 6;
   2707  1.1  christos 
   2708  1.1  christos static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
   2709  1.1  christos                                               1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
   2710  1.1  christos static const U32 OF_defaultNormLog = 5;
   2711  1.1  christos 
   2712  1.1  christos 
   2713  1.1  christos /*-*******************************************
   2714  1.1  christos *  Shared functions to include for inlining
   2715  1.1  christos *********************************************/
   2716  1.1  christos static void ZSTDv07_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
   2717  1.1  christos #define COPY8(d,s) { ZSTDv07_copy8(d,s); d+=8; s+=8; }
   2718  1.1  christos 
   2719  1.1  christos /*! ZSTDv07_wildcopy() :
   2720  1.1  christos *   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
   2721  1.1  christos #define WILDCOPY_OVERLENGTH 8
   2722  1.1  christos MEM_STATIC void ZSTDv07_wildcopy(void* dst, const void* src, ptrdiff_t length)
   2723  1.1  christos {
   2724  1.1  christos     const BYTE* ip = (const BYTE*)src;
   2725  1.1  christos     BYTE* op = (BYTE*)dst;
   2726  1.1  christos     BYTE* const oend = op + length;
   2727  1.1  christos     do
   2728  1.1  christos         COPY8(op, ip)
   2729  1.1  christos     while (op < oend);
   2730  1.1  christos }
   2731  1.1  christos 
   2732  1.1  christos 
   2733  1.1  christos /*-*******************************************
   2734  1.1  christos *  Private interfaces
   2735  1.1  christos *********************************************/
   2736  1.1  christos typedef struct ZSTDv07_stats_s ZSTDv07_stats_t;
   2737  1.1  christos 
   2738  1.1  christos typedef struct {
   2739  1.1  christos     U32 off;
   2740  1.1  christos     U32 len;
   2741  1.1  christos } ZSTDv07_match_t;
   2742  1.1  christos 
   2743  1.1  christos typedef struct {
   2744  1.1  christos     U32 price;
   2745  1.1  christos     U32 off;
   2746  1.1  christos     U32 mlen;
   2747  1.1  christos     U32 litlen;
   2748  1.1  christos     U32 rep[ZSTDv07_REP_INIT];
   2749  1.1  christos } ZSTDv07_optimal_t;
   2750  1.1  christos 
   2751  1.1  christos struct ZSTDv07_stats_s { U32 unused; };
   2752  1.1  christos 
   2753  1.1  christos typedef struct {
   2754  1.1  christos     void* buffer;
   2755  1.1  christos     U32*  offsetStart;
   2756  1.1  christos     U32*  offset;
   2757  1.1  christos     BYTE* offCodeStart;
   2758  1.1  christos     BYTE* litStart;
   2759  1.1  christos     BYTE* lit;
   2760  1.1  christos     U16*  litLengthStart;
   2761  1.1  christos     U16*  litLength;
   2762  1.1  christos     BYTE* llCodeStart;
   2763  1.1  christos     U16*  matchLengthStart;
   2764  1.1  christos     U16*  matchLength;
   2765  1.1  christos     BYTE* mlCodeStart;
   2766  1.1  christos     U32   longLengthID;   /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
   2767  1.1  christos     U32   longLengthPos;
   2768  1.1  christos     /* opt */
   2769  1.1  christos     ZSTDv07_optimal_t* priceTable;
   2770  1.1  christos     ZSTDv07_match_t* matchTable;
   2771  1.1  christos     U32* matchLengthFreq;
   2772  1.1  christos     U32* litLengthFreq;
   2773  1.1  christos     U32* litFreq;
   2774  1.1  christos     U32* offCodeFreq;
   2775  1.1  christos     U32  matchLengthSum;
   2776  1.1  christos     U32  matchSum;
   2777  1.1  christos     U32  litLengthSum;
   2778  1.1  christos     U32  litSum;
   2779  1.1  christos     U32  offCodeSum;
   2780  1.1  christos     U32  log2matchLengthSum;
   2781  1.1  christos     U32  log2matchSum;
   2782  1.1  christos     U32  log2litLengthSum;
   2783  1.1  christos     U32  log2litSum;
   2784  1.1  christos     U32  log2offCodeSum;
   2785  1.1  christos     U32  factor;
   2786  1.1  christos     U32  cachedPrice;
   2787  1.1  christos     U32  cachedLitLength;
   2788  1.1  christos     const BYTE* cachedLiterals;
   2789  1.1  christos     ZSTDv07_stats_t stats;
   2790  1.1  christos } seqStore_t;
   2791  1.1  christos 
   2792  1.1  christos void ZSTDv07_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);
   2793  1.1  christos 
   2794  1.1  christos /* custom memory allocation functions */
   2795  1.1  christos static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL };
   2796  1.1  christos 
   2797  1.1  christos #endif   /* ZSTDv07_CCOMMON_H_MODULE */
   2798  1.1  christos /*
   2799  1.1  christos     zstd - standard compression library
   2800  1.1  christos     Copyright (C) 2014-2016, Yann Collet.
   2801  1.1  christos 
   2802  1.1  christos     BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   2803  1.1  christos 
   2804  1.1  christos     Redistribution and use in source and binary forms, with or without
   2805  1.1  christos     modification, are permitted provided that the following conditions are
   2806  1.1  christos     met:
   2807  1.1  christos     * Redistributions of source code must retain the above copyright
   2808  1.1  christos     notice, this list of conditions and the following disclaimer.
   2809  1.1  christos     * Redistributions in binary form must reproduce the above
   2810  1.1  christos     copyright notice, this list of conditions and the following disclaimer
   2811  1.1  christos     in the documentation and/or other materials provided with the
   2812  1.1  christos     distribution.
   2813  1.1  christos     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   2814  1.1  christos     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   2815  1.1  christos     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   2816  1.1  christos     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   2817  1.1  christos     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   2818  1.1  christos     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   2819  1.1  christos     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   2820  1.1  christos     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   2821  1.1  christos     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   2822  1.1  christos     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   2823  1.1  christos     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   2824  1.1  christos 
   2825  1.1  christos     You can contact the author at :
   2826  1.1  christos     - zstd homepage : https://facebook.github.io/zstd
   2827  1.1  christos */
   2828  1.1  christos 
   2829  1.1  christos /* ***************************************************************
   2830  1.1  christos *  Tuning parameters
   2831  1.1  christos *****************************************************************/
   2832  1.1  christos /*!
   2833  1.1  christos  * HEAPMODE :
   2834  1.1  christos  * Select how default decompression function ZSTDv07_decompress() will allocate memory,
   2835  1.1  christos  * in memory stack (0), or in memory heap (1, requires malloc())
   2836  1.1  christos  */
   2837  1.1  christos #ifndef ZSTDv07_HEAPMODE
   2838  1.1  christos #  define ZSTDv07_HEAPMODE 1
   2839  1.1  christos #endif
   2840  1.1  christos 
   2841  1.1  christos 
   2842  1.1  christos /*-*******************************************************
   2843  1.1  christos *  Compiler specifics
   2844  1.1  christos *********************************************************/
   2845  1.1  christos #ifdef _MSC_VER    /* Visual Studio */
   2846  1.1  christos #  include <intrin.h>                    /* For Visual 2005 */
   2847  1.1  christos #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
   2848  1.1  christos #  pragma warning(disable : 4324)        /* disable: C4324: padded structure */
   2849  1.1  christos #  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */
   2850  1.1  christos #endif
   2851  1.1  christos 
   2852  1.1  christos 
   2853  1.1  christos /*-*************************************
   2854  1.1  christos *  Macros
   2855  1.1  christos ***************************************/
   2856  1.1  christos #define ZSTDv07_isError ERR_isError   /* for inlining */
   2857  1.1  christos #define FSEv07_isError  ERR_isError
   2858  1.1  christos #define HUFv07_isError  ERR_isError
   2859  1.1  christos 
   2860  1.1  christos 
   2861  1.1  christos /*_*******************************************************
   2862  1.1  christos *  Memory operations
   2863  1.1  christos **********************************************************/
   2864  1.1  christos static void ZSTDv07_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
   2865  1.1  christos 
   2866  1.1  christos 
   2867  1.1  christos /*-*************************************************************
   2868  1.1  christos *   Context management
   2869  1.1  christos ***************************************************************/
   2870  1.1  christos typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
   2871  1.1  christos                ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
   2872  1.1  christos                ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTDv07_dStage;
   2873  1.1  christos 
   2874  1.1  christos struct ZSTDv07_DCtx_s
   2875  1.1  christos {
   2876  1.1  christos     FSEv07_DTable LLTable[FSEv07_DTABLE_SIZE_U32(LLFSELog)];
   2877  1.1  christos     FSEv07_DTable OffTable[FSEv07_DTABLE_SIZE_U32(OffFSELog)];
   2878  1.1  christos     FSEv07_DTable MLTable[FSEv07_DTABLE_SIZE_U32(MLFSELog)];
   2879  1.1  christos     HUFv07_DTable hufTable[HUFv07_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];  /* can accommodate HUFv07_decompress4X */
   2880  1.1  christos     const void* previousDstEnd;
   2881  1.1  christos     const void* base;
   2882  1.1  christos     const void* vBase;
   2883  1.1  christos     const void* dictEnd;
   2884  1.1  christos     size_t expected;
   2885  1.1  christos     U32 rep[3];
   2886  1.1  christos     ZSTDv07_frameParams fParams;
   2887  1.1  christos     blockType_t bType;   /* used in ZSTDv07_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
   2888  1.1  christos     ZSTDv07_dStage stage;
   2889  1.1  christos     U32 litEntropy;
   2890  1.1  christos     U32 fseEntropy;
   2891  1.1  christos     XXH64_state_t xxhState;
   2892  1.1  christos     size_t headerSize;
   2893  1.1  christos     U32 dictID;
   2894  1.1  christos     const BYTE* litPtr;
   2895  1.1  christos     ZSTDv07_customMem customMem;
   2896  1.1  christos     size_t litSize;
   2897  1.1  christos     BYTE litBuffer[ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
   2898  1.1  christos     BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];
   2899  1.1  christos };  /* typedef'd to ZSTDv07_DCtx within "zstd_static.h" */
   2900  1.1  christos 
   2901  1.1  christos int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx);
   2902  1.1  christos 
   2903  1.1  christos size_t ZSTDv07_sizeofDCtx (const ZSTDv07_DCtx* dctx) { return sizeof(*dctx); }
   2904  1.1  christos 
   2905  1.1  christos size_t ZSTDv07_estimateDCtxSize(void) { return sizeof(ZSTDv07_DCtx); }
   2906  1.1  christos 
   2907  1.1  christos size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx)
   2908  1.1  christos {
   2909  1.1  christos     dctx->expected = ZSTDv07_frameHeaderSize_min;
   2910  1.1  christos     dctx->stage = ZSTDds_getFrameHeaderSize;
   2911  1.1  christos     dctx->previousDstEnd = NULL;
   2912  1.1  christos     dctx->base = NULL;
   2913  1.1  christos     dctx->vBase = NULL;
   2914  1.1  christos     dctx->dictEnd = NULL;
   2915  1.1  christos     dctx->hufTable[0] = (HUFv07_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);
   2916  1.1  christos     dctx->litEntropy = dctx->fseEntropy = 0;
   2917  1.1  christos     dctx->dictID = 0;
   2918  1.1  christos     { int i; for (i=0; i<ZSTDv07_REP_NUM; i++) dctx->rep[i] = repStartValue[i]; }
   2919  1.1  christos     return 0;
   2920  1.1  christos }
   2921  1.1  christos 
   2922  1.1  christos ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem)
   2923  1.1  christos {
   2924  1.1  christos     ZSTDv07_DCtx* dctx;
   2925  1.1  christos 
   2926  1.1  christos     if (!customMem.customAlloc && !customMem.customFree)
   2927  1.1  christos         customMem = defaultCustomMem;
   2928  1.1  christos 
   2929  1.1  christos     if (!customMem.customAlloc || !customMem.customFree)
   2930  1.1  christos         return NULL;
   2931  1.1  christos 
   2932  1.1  christos     dctx = (ZSTDv07_DCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTDv07_DCtx));
   2933  1.1  christos     if (!dctx) return NULL;
   2934  1.1  christos     memcpy(&dctx->customMem, &customMem, sizeof(ZSTDv07_customMem));
   2935  1.1  christos     ZSTDv07_decompressBegin(dctx);
   2936  1.1  christos     return dctx;
   2937  1.1  christos }
   2938  1.1  christos 
   2939  1.1  christos ZSTDv07_DCtx* ZSTDv07_createDCtx(void)
   2940  1.1  christos {
   2941  1.1  christos     return ZSTDv07_createDCtx_advanced(defaultCustomMem);
   2942  1.1  christos }
   2943  1.1  christos 
   2944  1.1  christos size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx)
   2945  1.1  christos {
   2946  1.1  christos     if (dctx==NULL) return 0;   /* support free on NULL */
   2947  1.1  christos     dctx->customMem.customFree(dctx->customMem.opaque, dctx);
   2948  1.1  christos     return 0;   /* reserved as a potential error code in the future */
   2949  1.1  christos }
   2950  1.1  christos 
   2951  1.1  christos void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dstDCtx, const ZSTDv07_DCtx* srcDCtx)
   2952  1.1  christos {
   2953  1.1  christos     memcpy(dstDCtx, srcDCtx,
   2954  1.1  christos            sizeof(ZSTDv07_DCtx) - (ZSTDv07_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTDv07_frameHeaderSize_max));  /* no need to copy workspace */
   2955  1.1  christos }
   2956  1.1  christos 
   2957  1.1  christos 
   2958  1.1  christos /*-*************************************************************
   2959  1.1  christos *   Decompression section
   2960  1.1  christos ***************************************************************/
   2961  1.1  christos 
   2962  1.1  christos /* Frame format description
   2963  1.1  christos    Frame Header -  [ Block Header - Block ] - Frame End
   2964  1.1  christos    1) Frame Header
   2965  1.1  christos       - 4 bytes - Magic Number : ZSTDv07_MAGICNUMBER (defined within zstd.h)
   2966  1.1  christos       - 1 byte  - Frame Descriptor
   2967  1.1  christos    2) Block Header
   2968  1.1  christos       - 3 bytes, starting with a 2-bits descriptor
   2969  1.1  christos                  Uncompressed, Compressed, Frame End, unused
   2970  1.1  christos    3) Block
   2971  1.1  christos       See Block Format Description
   2972  1.1  christos    4) Frame End
   2973  1.1  christos       - 3 bytes, compatible with Block Header
   2974  1.1  christos */
   2975  1.1  christos 
   2976  1.1  christos 
   2977  1.1  christos /* Frame Header :
   2978  1.1  christos 
   2979  1.1  christos    1 byte - FrameHeaderDescription :
   2980  1.1  christos    bit 0-1 : dictID (0, 1, 2 or 4 bytes)
   2981  1.1  christos    bit 2   : checksumFlag
   2982  1.1  christos    bit 3   : reserved (must be zero)
   2983  1.1  christos    bit 4   : reserved (unused, can be any value)
   2984  1.1  christos    bit 5   : Single Segment (if 1, WindowLog byte is not present)
   2985  1.1  christos    bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8)
   2986  1.1  christos              if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;
   2987  1.1  christos 
   2988  1.1  christos    Optional : WindowLog (0 or 1 byte)
   2989  1.1  christos    bit 0-2 : octal Fractional (1/8th)
   2990  1.1  christos    bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)
   2991  1.1  christos 
   2992  1.1  christos    Optional : dictID (0, 1, 2 or 4 bytes)
   2993  1.1  christos    Automatic adaptation
   2994  1.1  christos    0 : no dictID
   2995  1.1  christos    1 : 1 - 255
   2996  1.1  christos    2 : 256 - 65535
   2997  1.1  christos    4 : all other values
   2998  1.1  christos 
   2999  1.1  christos    Optional : content size (0, 1, 2, 4 or 8 bytes)
   3000  1.1  christos    0 : unknown          (fcfs==0 and swl==0)
   3001  1.1  christos    1 : 0-255 bytes      (fcfs==0 and swl==1)
   3002  1.1  christos    2 : 256 - 65535+256  (fcfs==1)
   3003  1.1  christos    4 : 0 - 4GB-1        (fcfs==2)
   3004  1.1  christos    8 : 0 - 16EB-1       (fcfs==3)
   3005  1.1  christos */
   3006  1.1  christos 
   3007  1.1  christos 
   3008  1.1  christos /* Compressed Block, format description
   3009  1.1  christos 
   3010  1.1  christos    Block = Literal Section - Sequences Section
   3011  1.1  christos    Prerequisite : size of (compressed) block, maximum size of regenerated data
   3012  1.1  christos 
   3013  1.1  christos    1) Literal Section
   3014  1.1  christos 
   3015  1.1  christos    1.1) Header : 1-5 bytes
   3016  1.1  christos         flags: 2 bits
   3017  1.1  christos             00 compressed by Huff0
   3018  1.1  christos             01 unused
   3019  1.1  christos             10 is Raw (uncompressed)
   3020  1.1  christos             11 is Rle
   3021  1.1  christos             Note : using 01 => Huff0 with precomputed table ?
   3022  1.1  christos             Note : delta map ? => compressed ?
   3023  1.1  christos 
   3024  1.1  christos    1.1.1) Huff0-compressed literal block : 3-5 bytes
   3025  1.1  christos             srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
   3026  1.1  christos             srcSize < 1 KB => 3 bytes (2-2-10-10)
   3027  1.1  christos             srcSize < 16KB => 4 bytes (2-2-14-14)
   3028  1.1  christos             else           => 5 bytes (2-2-18-18)
   3029  1.1  christos             big endian convention
   3030  1.1  christos 
   3031  1.1  christos    1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
   3032  1.1  christos         size :  5 bits: (IS_RAW<<6) + (0<<4) + size
   3033  1.1  christos                12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
   3034  1.1  christos                         size&255
   3035  1.1  christos                20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
   3036  1.1  christos                         size>>8&255
   3037  1.1  christos                         size&255
   3038  1.1  christos 
   3039  1.1  christos    1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
   3040  1.1  christos         size :  5 bits: (IS_RLE<<6) + (0<<4) + size
   3041  1.1  christos                12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
   3042  1.1  christos                         size&255
   3043  1.1  christos                20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
   3044  1.1  christos                         size>>8&255
   3045  1.1  christos                         size&255
   3046  1.1  christos 
   3047  1.1  christos    1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
   3048  1.1  christos             srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
   3049  1.1  christos             srcSize < 1 KB => 3 bytes (2-2-10-10)
   3050  1.1  christos             srcSize < 16KB => 4 bytes (2-2-14-14)
   3051  1.1  christos             else           => 5 bytes (2-2-18-18)
   3052  1.1  christos             big endian convention
   3053  1.1  christos 
   3054  1.1  christos         1- CTable available (stored into workspace ?)
   3055  1.1  christos         2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
   3056  1.1  christos 
   3057  1.1  christos 
   3058  1.1  christos    1.2) Literal block content
   3059  1.1  christos 
   3060  1.1  christos    1.2.1) Huff0 block, using sizes from header
   3061  1.1  christos         See Huff0 format
   3062  1.1  christos 
   3063  1.1  christos    1.2.2) Huff0 block, using prepared table
   3064  1.1  christos 
   3065  1.1  christos    1.2.3) Raw content
   3066  1.1  christos 
   3067  1.1  christos    1.2.4) single byte
   3068  1.1  christos 
   3069  1.1  christos 
   3070  1.1  christos    2) Sequences section
   3071  1.1  christos       TO DO
   3072  1.1  christos */
   3073  1.1  christos 
   3074  1.1  christos /** ZSTDv07_frameHeaderSize() :
   3075  1.1  christos *   srcSize must be >= ZSTDv07_frameHeaderSize_min.
   3076  1.1  christos *   @return : size of the Frame Header */
   3077  1.1  christos static size_t ZSTDv07_frameHeaderSize(const void* src, size_t srcSize)
   3078  1.1  christos {
   3079  1.1  christos     if (srcSize < ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);
   3080  1.1  christos     {   BYTE const fhd = ((const BYTE*)src)[4];
   3081  1.1  christos         U32 const dictID= fhd & 3;
   3082  1.1  christos         U32 const directMode = (fhd >> 5) & 1;
   3083  1.1  christos         U32 const fcsId = fhd >> 6;
   3084  1.1  christos         return ZSTDv07_frameHeaderSize_min + !directMode + ZSTDv07_did_fieldSize[dictID] + ZSTDv07_fcs_fieldSize[fcsId]
   3085  1.1  christos                 + (directMode && !ZSTDv07_fcs_fieldSize[fcsId]);
   3086  1.1  christos     }
   3087  1.1  christos }
   3088  1.1  christos 
   3089  1.1  christos 
   3090  1.1  christos /** ZSTDv07_getFrameParams() :
   3091  1.1  christos *   decode Frame Header, or require larger `srcSize`.
   3092  1.1  christos *   @return : 0, `fparamsPtr` is correctly filled,
   3093  1.1  christos *            >0, `srcSize` is too small, result is expected `srcSize`,
   3094  1.1  christos *             or an error code, which can be tested using ZSTDv07_isError() */
   3095  1.1  christos size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize)
   3096  1.1  christos {
   3097  1.1  christos     const BYTE* ip = (const BYTE*)src;
   3098  1.1  christos 
   3099  1.1  christos     if (srcSize < ZSTDv07_frameHeaderSize_min) return ZSTDv07_frameHeaderSize_min;
   3100  1.1  christos     memset(fparamsPtr, 0, sizeof(*fparamsPtr));
   3101  1.1  christos     if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
   3102  1.1  christos         if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {
   3103  1.1  christos             if (srcSize < ZSTDv07_skippableHeaderSize) return ZSTDv07_skippableHeaderSize; /* magic number + skippable frame length */
   3104  1.1  christos             fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
   3105  1.1  christos             fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
   3106  1.1  christos             return 0;
   3107  1.1  christos         }
   3108  1.1  christos         return ERROR(prefix_unknown);
   3109  1.1  christos     }
   3110  1.1  christos 
   3111  1.1  christos     /* ensure there is enough `srcSize` to fully read/decode frame header */
   3112  1.1  christos     { size_t const fhsize = ZSTDv07_frameHeaderSize(src, srcSize);
   3113  1.1  christos       if (srcSize < fhsize) return fhsize; }
   3114  1.1  christos 
   3115  1.1  christos     {   BYTE const fhdByte = ip[4];
   3116  1.1  christos         size_t pos = 5;
   3117  1.1  christos         U32 const dictIDSizeCode = fhdByte&3;
   3118  1.1  christos         U32 const checksumFlag = (fhdByte>>2)&1;
   3119  1.1  christos         U32 const directMode = (fhdByte>>5)&1;
   3120  1.1  christos         U32 const fcsID = fhdByte>>6;
   3121  1.1  christos         U32 const windowSizeMax = 1U << ZSTDv07_WINDOWLOG_MAX;
   3122  1.1  christos         U32 windowSize = 0;
   3123  1.1  christos         U32 dictID = 0;
   3124  1.1  christos         U64 frameContentSize = 0;
   3125  1.1  christos         if ((fhdByte & 0x08) != 0)   /* reserved bits, which must be zero */
   3126  1.1  christos             return ERROR(frameParameter_unsupported);
   3127  1.1  christos         if (!directMode) {
   3128  1.1  christos             BYTE const wlByte = ip[pos++];
   3129  1.1  christos             U32 const windowLog = (wlByte >> 3) + ZSTDv07_WINDOWLOG_ABSOLUTEMIN;
   3130  1.1  christos             if (windowLog > ZSTDv07_WINDOWLOG_MAX)
   3131  1.1  christos                 return ERROR(frameParameter_unsupported);
   3132  1.1  christos             windowSize = (1U << windowLog);
   3133  1.1  christos             windowSize += (windowSize >> 3) * (wlByte&7);
   3134  1.1  christos         }
   3135  1.1  christos 
   3136  1.1  christos         switch(dictIDSizeCode)
   3137  1.1  christos         {
   3138  1.1  christos             default:   /* impossible */
   3139  1.1  christos             case 0 : break;
   3140  1.1  christos             case 1 : dictID = ip[pos]; pos++; break;
   3141  1.1  christos             case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
   3142  1.1  christos             case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
   3143  1.1  christos         }
   3144  1.1  christos         switch(fcsID)
   3145  1.1  christos         {
   3146  1.1  christos             default:   /* impossible */
   3147  1.1  christos             case 0 : if (directMode) frameContentSize = ip[pos]; break;
   3148  1.1  christos             case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
   3149  1.1  christos             case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
   3150  1.1  christos             case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
   3151  1.1  christos         }
   3152  1.1  christos         if (!windowSize) windowSize = (U32)frameContentSize;
   3153  1.1  christos         if (windowSize > windowSizeMax)
   3154  1.1  christos             return ERROR(frameParameter_unsupported);
   3155  1.1  christos         fparamsPtr->frameContentSize = frameContentSize;
   3156  1.1  christos         fparamsPtr->windowSize = windowSize;
   3157  1.1  christos         fparamsPtr->dictID = dictID;
   3158  1.1  christos         fparamsPtr->checksumFlag = checksumFlag;
   3159  1.1  christos     }
   3160  1.1  christos     return 0;
   3161  1.1  christos }
   3162  1.1  christos 
   3163  1.1  christos 
   3164  1.1  christos /** ZSTDv07_getDecompressedSize() :
   3165  1.1  christos *   compatible with legacy mode
   3166  1.1  christos *   @return : decompressed size if known, 0 otherwise
   3167  1.1  christos               note : 0 can mean any of the following :
   3168  1.1  christos                    - decompressed size is not provided within frame header
   3169  1.1  christos                    - frame header unknown / not supported
   3170  1.1  christos                    - frame header not completely provided (`srcSize` too small) */
   3171  1.1  christos unsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize)
   3172  1.1  christos {
   3173  1.1  christos     ZSTDv07_frameParams fparams;
   3174  1.1  christos     size_t const frResult = ZSTDv07_getFrameParams(&fparams, src, srcSize);
   3175  1.1  christos     if (frResult!=0) return 0;
   3176  1.1  christos     return fparams.frameContentSize;
   3177  1.1  christos }
   3178  1.1  christos 
   3179  1.1  christos 
   3180  1.1  christos /** ZSTDv07_decodeFrameHeader() :
   3181  1.1  christos *   `srcSize` must be the size provided by ZSTDv07_frameHeaderSize().
   3182  1.1  christos *   @return : 0 if success, or an error code, which can be tested using ZSTDv07_isError() */
   3183  1.1  christos static size_t ZSTDv07_decodeFrameHeader(ZSTDv07_DCtx* dctx, const void* src, size_t srcSize)
   3184  1.1  christos {
   3185  1.1  christos     size_t const result = ZSTDv07_getFrameParams(&(dctx->fParams), src, srcSize);
   3186  1.1  christos     if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);
   3187  1.1  christos     if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
   3188  1.1  christos     return result;
   3189  1.1  christos }
   3190  1.1  christos 
   3191  1.1  christos 
   3192  1.1  christos typedef struct
   3193  1.1  christos {
   3194  1.1  christos     blockType_t blockType;
   3195  1.1  christos     U32 origSize;
   3196  1.1  christos } blockProperties_t;
   3197  1.1  christos 
   3198  1.1  christos /*! ZSTDv07_getcBlockSize() :
   3199  1.1  christos *   Provides the size of compressed block from block header `src` */
   3200  1.1  christos static size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
   3201  1.1  christos {
   3202  1.1  christos     const BYTE* const in = (const BYTE*)src;
   3203  1.1  christos     U32 cSize;
   3204  1.1  christos 
   3205  1.1  christos     if (srcSize < ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
   3206  1.1  christos 
   3207  1.1  christos     bpPtr->blockType = (blockType_t)((*in) >> 6);
   3208  1.1  christos     cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
   3209  1.1  christos     bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
   3210  1.1  christos 
   3211  1.1  christos     if (bpPtr->blockType == bt_end) return 0;
   3212  1.1  christos     if (bpPtr->blockType == bt_rle) return 1;
   3213  1.1  christos     return cSize;
   3214  1.1  christos }
   3215  1.1  christos 
   3216  1.1  christos 
   3217  1.1  christos static size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   3218  1.1  christos {
   3219  1.1  christos     if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
   3220  1.1  christos     if (srcSize > 0) {
   3221  1.1  christos         memcpy(dst, src, srcSize);
   3222  1.1  christos     }
   3223  1.1  christos     return srcSize;
   3224  1.1  christos }
   3225  1.1  christos 
   3226  1.1  christos 
   3227  1.1  christos /*! ZSTDv07_decodeLiteralsBlock() :
   3228  1.1  christos     @return : nb of bytes read from src (< srcSize ) */
   3229  1.1  christos static size_t ZSTDv07_decodeLiteralsBlock(ZSTDv07_DCtx* dctx,
   3230  1.1  christos                           const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */
   3231  1.1  christos {
   3232  1.1  christos     const BYTE* const istart = (const BYTE*) src;
   3233  1.1  christos 
   3234  1.1  christos     if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
   3235  1.1  christos 
   3236  1.1  christos     switch((litBlockType_t)(istart[0]>> 6))
   3237  1.1  christos     {
   3238  1.1  christos     case lbt_huffman:
   3239  1.1  christos         {   size_t litSize, litCSize, singleStream=0;
   3240  1.1  christos             U32 lhSize = (istart[0] >> 4) & 3;
   3241  1.1  christos             if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */
   3242  1.1  christos             switch(lhSize)
   3243  1.1  christos             {
   3244  1.1  christos             case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */
   3245  1.1  christos                 /* 2 - 2 - 10 - 10 */
   3246  1.1  christos                 lhSize=3;
   3247  1.1  christos                 singleStream = istart[0] & 16;
   3248  1.1  christos                 litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);
   3249  1.1  christos                 litCSize = ((istart[1] &  3) << 8) + istart[2];
   3250  1.1  christos                 break;
   3251  1.1  christos             case 2:
   3252  1.1  christos                 /* 2 - 2 - 14 - 14 */
   3253  1.1  christos                 lhSize=4;
   3254  1.1  christos                 litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
   3255  1.1  christos                 litCSize = ((istart[2] & 63) <<  8) + istart[3];
   3256  1.1  christos                 break;
   3257  1.1  christos             case 3:
   3258  1.1  christos                 /* 2 - 2 - 18 - 18 */
   3259  1.1  christos                 lhSize=5;
   3260  1.1  christos                 litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
   3261  1.1  christos                 litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];
   3262  1.1  christos                 break;
   3263  1.1  christos             }
   3264  1.1  christos             if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
   3265  1.1  christos             if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
   3266  1.1  christos 
   3267  1.1  christos             if (HUFv07_isError(singleStream ?
   3268  1.1  christos                             HUFv07_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
   3269  1.1  christos                             HUFv07_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
   3270  1.1  christos                 return ERROR(corruption_detected);
   3271  1.1  christos 
   3272  1.1  christos             dctx->litPtr = dctx->litBuffer;
   3273  1.1  christos             dctx->litSize = litSize;
   3274  1.1  christos             dctx->litEntropy = 1;
   3275  1.1  christos             memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
   3276  1.1  christos             return litCSize + lhSize;
   3277  1.1  christos         }
   3278  1.1  christos     case lbt_repeat:
   3279  1.1  christos         {   size_t litSize, litCSize;
   3280  1.1  christos             U32 lhSize = ((istart[0]) >> 4) & 3;
   3281  1.1  christos             if (lhSize != 1)  /* only case supported for now : small litSize, single stream */
   3282  1.1  christos                 return ERROR(corruption_detected);
   3283  1.1  christos             if (dctx->litEntropy==0)
   3284  1.1  christos                 return ERROR(dictionary_corrupted);
   3285  1.1  christos 
   3286  1.1  christos             /* 2 - 2 - 10 - 10 */
   3287  1.1  christos             lhSize=3;
   3288  1.1  christos             litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);
   3289  1.1  christos             litCSize = ((istart[1] &  3) << 8) + istart[2];
   3290  1.1  christos             if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
   3291  1.1  christos 
   3292  1.1  christos             {   size_t const errorCode = HUFv07_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable);
   3293  1.1  christos                 if (HUFv07_isError(errorCode)) return ERROR(corruption_detected);
   3294  1.1  christos             }
   3295  1.1  christos             dctx->litPtr = dctx->litBuffer;
   3296  1.1  christos             dctx->litSize = litSize;
   3297  1.1  christos             memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
   3298  1.1  christos             return litCSize + lhSize;
   3299  1.1  christos         }
   3300  1.1  christos     case lbt_raw:
   3301  1.1  christos         {   size_t litSize;
   3302  1.1  christos             U32 lhSize = ((istart[0]) >> 4) & 3;
   3303  1.1  christos             switch(lhSize)
   3304  1.1  christos             {
   3305  1.1  christos             case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */
   3306  1.1  christos                 lhSize=1;
   3307  1.1  christos                 litSize = istart[0] & 31;
   3308  1.1  christos                 break;
   3309  1.1  christos             case 2:
   3310  1.1  christos                 litSize = ((istart[0] & 15) << 8) + istart[1];
   3311  1.1  christos                 break;
   3312  1.1  christos             case 3:
   3313  1.1  christos                 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
   3314  1.1  christos                 break;
   3315  1.1  christos             }
   3316  1.1  christos 
   3317  1.1  christos             if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */
   3318  1.1  christos                 if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
   3319  1.1  christos                 memcpy(dctx->litBuffer, istart+lhSize, litSize);
   3320  1.1  christos                 dctx->litPtr = dctx->litBuffer;
   3321  1.1  christos                 dctx->litSize = litSize;
   3322  1.1  christos                 memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
   3323  1.1  christos                 return lhSize+litSize;
   3324  1.1  christos             }
   3325  1.1  christos             /* direct reference into compressed stream */
   3326  1.1  christos             dctx->litPtr = istart+lhSize;
   3327  1.1  christos             dctx->litSize = litSize;
   3328  1.1  christos             return lhSize+litSize;
   3329  1.1  christos         }
   3330  1.1  christos     case lbt_rle:
   3331  1.1  christos         {   size_t litSize;
   3332  1.1  christos             U32 lhSize = ((istart[0]) >> 4) & 3;
   3333  1.1  christos             switch(lhSize)
   3334  1.1  christos             {
   3335  1.1  christos             case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */
   3336  1.1  christos                 lhSize = 1;
   3337  1.1  christos                 litSize = istart[0] & 31;
   3338  1.1  christos                 break;
   3339  1.1  christos             case 2:
   3340  1.1  christos                 litSize = ((istart[0] & 15) << 8) + istart[1];
   3341  1.1  christos                 break;
   3342  1.1  christos             case 3:
   3343  1.1  christos                 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
   3344  1.1  christos                 if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
   3345  1.1  christos                 break;
   3346  1.1  christos             }
   3347  1.1  christos             if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
   3348  1.1  christos             memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
   3349  1.1  christos             dctx->litPtr = dctx->litBuffer;
   3350  1.1  christos             dctx->litSize = litSize;
   3351  1.1  christos             return lhSize+1;
   3352  1.1  christos         }
   3353  1.1  christos     default:
   3354  1.1  christos         return ERROR(corruption_detected);   /* impossible */
   3355  1.1  christos     }
   3356  1.1  christos }
   3357  1.1  christos 
   3358  1.1  christos 
   3359  1.1  christos /*! ZSTDv07_buildSeqTable() :
   3360  1.1  christos     @return : nb bytes read from src,
   3361  1.1  christos               or an error code if it fails, testable with ZSTDv07_isError()
   3362  1.1  christos */
   3363  1.1  christos static size_t ZSTDv07_buildSeqTable(FSEv07_DTable* DTable, U32 type, U32 max, U32 maxLog,
   3364  1.1  christos                                  const void* src, size_t srcSize,
   3365  1.1  christos                                  const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)
   3366  1.1  christos {
   3367  1.1  christos     switch(type)
   3368  1.1  christos     {
   3369  1.1  christos     case FSEv07_ENCODING_RLE :
   3370  1.1  christos         if (!srcSize) return ERROR(srcSize_wrong);
   3371  1.1  christos         if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
   3372  1.1  christos         FSEv07_buildDTable_rle(DTable, *(const BYTE*)src);   /* if *src > max, data is corrupted */
   3373  1.1  christos         return 1;
   3374  1.1  christos     case FSEv07_ENCODING_RAW :
   3375  1.1  christos         FSEv07_buildDTable(DTable, defaultNorm, max, defaultLog);
   3376  1.1  christos         return 0;
   3377  1.1  christos     case FSEv07_ENCODING_STATIC:
   3378  1.1  christos         if (!flagRepeatTable) return ERROR(corruption_detected);
   3379  1.1  christos         return 0;
   3380  1.1  christos     default :   /* impossible */
   3381  1.1  christos     case FSEv07_ENCODING_DYNAMIC :
   3382  1.1  christos         {   U32 tableLog;
   3383  1.1  christos             S16 norm[MaxSeq+1];
   3384  1.1  christos             size_t const headerSize = FSEv07_readNCount(norm, &max, &tableLog, src, srcSize);
   3385  1.1  christos             if (FSEv07_isError(headerSize)) return ERROR(corruption_detected);
   3386  1.1  christos             if (tableLog > maxLog) return ERROR(corruption_detected);
   3387  1.1  christos             FSEv07_buildDTable(DTable, norm, max, tableLog);
   3388  1.1  christos             return headerSize;
   3389  1.1  christos     }   }
   3390  1.1  christos }
   3391  1.1  christos 
   3392  1.1  christos 
   3393  1.1  christos static size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,
   3394  1.1  christos                              FSEv07_DTable* DTableLL, FSEv07_DTable* DTableML, FSEv07_DTable* DTableOffb, U32 flagRepeatTable,
   3395  1.1  christos                              const void* src, size_t srcSize)
   3396  1.1  christos {
   3397  1.1  christos     const BYTE* const istart = (const BYTE*)src;
   3398  1.1  christos     const BYTE* const iend = istart + srcSize;
   3399  1.1  christos     const BYTE* ip = istart;
   3400  1.1  christos 
   3401  1.1  christos     /* check */
   3402  1.1  christos     if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
   3403  1.1  christos 
   3404  1.1  christos     /* SeqHead */
   3405  1.1  christos     {   int nbSeq = *ip++;
   3406  1.1  christos         if (!nbSeq) { *nbSeqPtr=0; return 1; }
   3407  1.1  christos         if (nbSeq > 0x7F) {
   3408  1.1  christos             if (nbSeq == 0xFF) {
   3409  1.1  christos                 if (ip+2 > iend) return ERROR(srcSize_wrong);
   3410  1.1  christos                 nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
   3411  1.1  christos             } else {
   3412  1.1  christos                 if (ip >= iend) return ERROR(srcSize_wrong);
   3413  1.1  christos                 nbSeq = ((nbSeq-0x80)<<8) + *ip++;
   3414  1.1  christos             }
   3415  1.1  christos         }
   3416  1.1  christos         *nbSeqPtr = nbSeq;
   3417  1.1  christos     }
   3418  1.1  christos 
   3419  1.1  christos     /* FSE table descriptors */
   3420  1.1  christos     if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */
   3421  1.1  christos     {   U32 const LLtype  = *ip >> 6;
   3422  1.1  christos         U32 const OFtype = (*ip >> 4) & 3;
   3423  1.1  christos         U32 const MLtype  = (*ip >> 2) & 3;
   3424  1.1  christos         ip++;
   3425  1.1  christos 
   3426  1.1  christos         /* Build DTables */
   3427  1.1  christos         {   size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);
   3428  1.1  christos             if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);
   3429  1.1  christos             ip += llhSize;
   3430  1.1  christos         }
   3431  1.1  christos         {   size_t const ofhSize = ZSTDv07_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);
   3432  1.1  christos             if (ZSTDv07_isError(ofhSize)) return ERROR(corruption_detected);
   3433  1.1  christos             ip += ofhSize;
   3434  1.1  christos         }
   3435  1.1  christos         {   size_t const mlhSize = ZSTDv07_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);
   3436  1.1  christos             if (ZSTDv07_isError(mlhSize)) return ERROR(corruption_detected);
   3437  1.1  christos             ip += mlhSize;
   3438  1.1  christos     }   }
   3439  1.1  christos 
   3440  1.1  christos     return ip-istart;
   3441  1.1  christos }
   3442  1.1  christos 
   3443  1.1  christos 
   3444  1.1  christos typedef struct {
   3445  1.1  christos     size_t litLength;
   3446  1.1  christos     size_t matchLength;
   3447  1.1  christos     size_t offset;
   3448  1.1  christos } seq_t;
   3449  1.1  christos 
   3450  1.1  christos typedef struct {
   3451  1.1  christos     BITv07_DStream_t DStream;
   3452  1.1  christos     FSEv07_DState_t stateLL;
   3453  1.1  christos     FSEv07_DState_t stateOffb;
   3454  1.1  christos     FSEv07_DState_t stateML;
   3455  1.1  christos     size_t prevOffset[ZSTDv07_REP_INIT];
   3456  1.1  christos } seqState_t;
   3457  1.1  christos 
   3458  1.1  christos 
   3459  1.1  christos static seq_t ZSTDv07_decodeSequence(seqState_t* seqState)
   3460  1.1  christos {
   3461  1.1  christos     seq_t seq;
   3462  1.1  christos 
   3463  1.1  christos     U32 const llCode = FSEv07_peekSymbol(&(seqState->stateLL));
   3464  1.1  christos     U32 const mlCode = FSEv07_peekSymbol(&(seqState->stateML));
   3465  1.1  christos     U32 const ofCode = FSEv07_peekSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */
   3466  1.1  christos 
   3467  1.1  christos     U32 const llBits = LL_bits[llCode];
   3468  1.1  christos     U32 const mlBits = ML_bits[mlCode];
   3469  1.1  christos     U32 const ofBits = ofCode;
   3470  1.1  christos     U32 const totalBits = llBits+mlBits+ofBits;
   3471  1.1  christos 
   3472  1.1  christos     static const U32 LL_base[MaxLL+1] = {
   3473  1.1  christos                              0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,
   3474  1.1  christos                             16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
   3475  1.1  christos                             0x2000, 0x4000, 0x8000, 0x10000 };
   3476  1.1  christos 
   3477  1.1  christos     static const U32 ML_base[MaxML+1] = {
   3478  1.1  christos                              3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,   14,    15,    16,    17,    18,
   3479  1.1  christos                             19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,   30,    31,    32,    33,    34,
   3480  1.1  christos                             35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
   3481  1.1  christos                             0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
   3482  1.1  christos 
   3483  1.1  christos     static const U32 OF_base[MaxOff+1] = {
   3484  1.1  christos                  0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,
   3485  1.1  christos                  0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,
   3486  1.1  christos                  0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
   3487  1.1  christos                  0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
   3488  1.1  christos 
   3489  1.1  christos     /* sequence */
   3490  1.1  christos     {   size_t offset;
   3491  1.1  christos         if (!ofCode)
   3492  1.1  christos             offset = 0;
   3493  1.1  christos         else {
   3494  1.1  christos             offset = OF_base[ofCode] + BITv07_readBits(&(seqState->DStream), ofBits);   /* <=  (ZSTDv07_WINDOWLOG_MAX-1) bits */
   3495  1.1  christos             if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));
   3496  1.1  christos         }
   3497  1.1  christos 
   3498  1.1  christos         if (ofCode <= 1) {
   3499  1.1  christos             if ((llCode == 0) & (offset <= 1)) offset = 1-offset;
   3500  1.1  christos             if (offset) {
   3501  1.1  christos                 size_t const temp = seqState->prevOffset[offset];
   3502  1.1  christos                 if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
   3503  1.1  christos                 seqState->prevOffset[1] = seqState->prevOffset[0];
   3504  1.1  christos                 seqState->prevOffset[0] = offset = temp;
   3505  1.1  christos             } else {
   3506  1.1  christos                 offset = seqState->prevOffset[0];
   3507  1.1  christos             }
   3508  1.1  christos         } else {
   3509  1.1  christos             seqState->prevOffset[2] = seqState->prevOffset[1];
   3510  1.1  christos             seqState->prevOffset[1] = seqState->prevOffset[0];
   3511  1.1  christos             seqState->prevOffset[0] = offset;
   3512  1.1  christos         }
   3513  1.1  christos         seq.offset = offset;
   3514  1.1  christos     }
   3515  1.1  christos 
   3516  1.1  christos     seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BITv07_readBits(&(seqState->DStream), mlBits) : 0);   /* <=  16 bits */
   3517  1.1  christos     if (MEM_32bits() && (mlBits+llBits>24)) BITv07_reloadDStream(&(seqState->DStream));
   3518  1.1  christos 
   3519  1.1  christos     seq.litLength = LL_base[llCode] + ((llCode>15) ? BITv07_readBits(&(seqState->DStream), llBits) : 0);   /* <=  16 bits */
   3520  1.1  christos     if (MEM_32bits() ||
   3521  1.1  christos        (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv07_reloadDStream(&(seqState->DStream));
   3522  1.1  christos 
   3523  1.1  christos     /* ANS state update */
   3524  1.1  christos     FSEv07_updateState(&(seqState->stateLL), &(seqState->DStream));   /* <=  9 bits */
   3525  1.1  christos     FSEv07_updateState(&(seqState->stateML), &(seqState->DStream));   /* <=  9 bits */
   3526  1.1  christos     if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));     /* <= 18 bits */
   3527  1.1  christos     FSEv07_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <=  8 bits */
   3528  1.1  christos 
   3529  1.1  christos     return seq;
   3530  1.1  christos }
   3531  1.1  christos 
   3532  1.1  christos 
   3533  1.1  christos static
   3534  1.1  christos size_t ZSTDv07_execSequence(BYTE* op,
   3535  1.1  christos                                 BYTE* const oend, seq_t sequence,
   3536  1.1  christos                                 const BYTE** litPtr, const BYTE* const litLimit,
   3537  1.1  christos                                 const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
   3538  1.1  christos {
   3539  1.1  christos     BYTE* const oLitEnd = op + sequence.litLength;
   3540  1.1  christos     size_t const sequenceLength = sequence.litLength + sequence.matchLength;
   3541  1.1  christos     BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */
   3542  1.1  christos     BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH;
   3543  1.1  christos     const BYTE* const iLitEnd = *litPtr + sequence.litLength;
   3544  1.1  christos     const BYTE* match = oLitEnd - sequence.offset;
   3545  1.1  christos 
   3546  1.1  christos     /* check */
   3547  1.1  christos     assert(oend >= op);
   3548  1.1  christos     if (sequence.litLength + WILDCOPY_OVERLENGTH > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
   3549  1.1  christos     if (sequenceLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
   3550  1.1  christos     assert(litLimit >= *litPtr);
   3551  1.1  christos     if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);;
   3552  1.1  christos 
   3553  1.1  christos     /* copy Literals */
   3554  1.1  christos     ZSTDv07_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
   3555  1.1  christos     op = oLitEnd;
   3556  1.1  christos     *litPtr = iLitEnd;   /* update for next sequence */
   3557  1.1  christos 
   3558  1.1  christos     /* copy Match */
   3559  1.1  christos     if (sequence.offset > (size_t)(oLitEnd - base)) {
   3560  1.1  christos         /* offset beyond prefix */
   3561  1.1  christos         if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
   3562  1.1  christos         match = dictEnd - (base-match);
   3563  1.1  christos         if (match + sequence.matchLength <= dictEnd) {
   3564  1.1  christos             memmove(oLitEnd, match, sequence.matchLength);
   3565  1.1  christos             return sequenceLength;
   3566  1.1  christos         }
   3567  1.1  christos         /* span extDict & currentPrefixSegment */
   3568  1.1  christos         {   size_t const length1 = (size_t)(dictEnd - match);
   3569  1.1  christos             memmove(oLitEnd, match, length1);
   3570  1.1  christos             op = oLitEnd + length1;
   3571  1.1  christos             sequence.matchLength -= length1;
   3572  1.1  christos             match = base;
   3573  1.1  christos             if (op > oend_w || sequence.matchLength < MINMATCH) {
   3574  1.1  christos               while (op < oMatchEnd) *op++ = *match++;
   3575  1.1  christos               return sequenceLength;
   3576  1.1  christos             }
   3577  1.1  christos     }   }
   3578  1.1  christos     /* Requirement: op <= oend_w */
   3579  1.1  christos 
   3580  1.1  christos     /* match within prefix */
   3581  1.1  christos     if (sequence.offset < 8) {
   3582  1.1  christos         /* close range match, overlap */
   3583  1.1  christos         static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */
   3584  1.1  christos         static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */
   3585  1.1  christos         int const sub2 = dec64table[sequence.offset];
   3586  1.1  christos         op[0] = match[0];
   3587  1.1  christos         op[1] = match[1];
   3588  1.1  christos         op[2] = match[2];
   3589  1.1  christos         op[3] = match[3];
   3590  1.1  christos         match += dec32table[sequence.offset];
   3591  1.1  christos         ZSTDv07_copy4(op+4, match);
   3592  1.1  christos         match -= sub2;
   3593  1.1  christos     } else {
   3594  1.1  christos         ZSTDv07_copy8(op, match);
   3595  1.1  christos     }
   3596  1.1  christos     op += 8; match += 8;
   3597  1.1  christos 
   3598  1.1  christos     if (oMatchEnd > oend-(16-MINMATCH)) {
   3599  1.1  christos         if (op < oend_w) {
   3600  1.1  christos             ZSTDv07_wildcopy(op, match, oend_w - op);
   3601  1.1  christos             match += oend_w - op;
   3602  1.1  christos             op = oend_w;
   3603  1.1  christos         }
   3604  1.1  christos         while (op < oMatchEnd) *op++ = *match++;
   3605  1.1  christos     } else {
   3606  1.1  christos         ZSTDv07_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */
   3607  1.1  christos     }
   3608  1.1  christos     return sequenceLength;
   3609  1.1  christos }
   3610  1.1  christos 
   3611  1.1  christos 
   3612  1.1  christos static size_t ZSTDv07_decompressSequences(
   3613  1.1  christos                                ZSTDv07_DCtx* dctx,
   3614  1.1  christos                                void* dst, size_t maxDstSize,
   3615  1.1  christos                          const void* seqStart, size_t seqSize)
   3616  1.1  christos {
   3617  1.1  christos     const BYTE* ip = (const BYTE*)seqStart;
   3618  1.1  christos     const BYTE* const iend = ip + seqSize;
   3619  1.1  christos     BYTE* const ostart = (BYTE*)dst;
   3620  1.1  christos     BYTE* const oend = ostart + maxDstSize;
   3621  1.1  christos     BYTE* op = ostart;
   3622  1.1  christos     const BYTE* litPtr = dctx->litPtr;
   3623  1.1  christos     const BYTE* const litEnd = litPtr + dctx->litSize;
   3624  1.1  christos     FSEv07_DTable* DTableLL = dctx->LLTable;
   3625  1.1  christos     FSEv07_DTable* DTableML = dctx->MLTable;
   3626  1.1  christos     FSEv07_DTable* DTableOffb = dctx->OffTable;
   3627  1.1  christos     const BYTE* const base = (const BYTE*) (dctx->base);
   3628  1.1  christos     const BYTE* const vBase = (const BYTE*) (dctx->vBase);
   3629  1.1  christos     const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
   3630  1.1  christos     int nbSeq;
   3631  1.1  christos 
   3632  1.1  christos     /* Build Decoding Tables */
   3633  1.1  christos     {   size_t const seqHSize = ZSTDv07_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);
   3634  1.1  christos         if (ZSTDv07_isError(seqHSize)) return seqHSize;
   3635  1.1  christos         ip += seqHSize;
   3636  1.1  christos     }
   3637  1.1  christos 
   3638  1.1  christos     /* Regen sequences */
   3639  1.1  christos     if (nbSeq) {
   3640  1.1  christos         seqState_t seqState;
   3641  1.1  christos         dctx->fseEntropy = 1;
   3642  1.1  christos         { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) seqState.prevOffset[i] = dctx->rep[i]; }
   3643  1.1  christos         { size_t const errorCode = BITv07_initDStream(&(seqState.DStream), ip, iend-ip);
   3644  1.1  christos           if (ERR_isError(errorCode)) return ERROR(corruption_detected); }
   3645  1.1  christos         FSEv07_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
   3646  1.1  christos         FSEv07_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
   3647  1.1  christos         FSEv07_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
   3648  1.1  christos 
   3649  1.1  christos         for ( ; (BITv07_reloadDStream(&(seqState.DStream)) <= BITv07_DStream_completed) && nbSeq ; ) {
   3650  1.1  christos             nbSeq--;
   3651  1.1  christos             {   seq_t const sequence = ZSTDv07_decodeSequence(&seqState);
   3652  1.1  christos                 size_t const oneSeqSize = ZSTDv07_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
   3653  1.1  christos                 if (ZSTDv07_isError(oneSeqSize)) return oneSeqSize;
   3654  1.1  christos                 op += oneSeqSize;
   3655  1.1  christos         }   }
   3656  1.1  christos 
   3657  1.1  christos         /* check if reached exact end */
   3658  1.1  christos         if (nbSeq) return ERROR(corruption_detected);
   3659  1.1  christos         /* save reps for next block */
   3660  1.1  christos         { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
   3661  1.1  christos     }
   3662  1.1  christos 
   3663  1.1  christos     /* last literal segment */
   3664  1.1  christos     {   size_t const lastLLSize = litEnd - litPtr;
   3665  1.1  christos         /* if (litPtr > litEnd) return ERROR(corruption_detected); */   /* too many literals already used */
   3666  1.1  christos         if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
   3667  1.1  christos         if (lastLLSize > 0) {
   3668  1.1  christos             memcpy(op, litPtr, lastLLSize);
   3669  1.1  christos             op += lastLLSize;
   3670  1.1  christos         }
   3671  1.1  christos     }
   3672  1.1  christos 
   3673  1.1  christos     return op-ostart;
   3674  1.1  christos }
   3675  1.1  christos 
   3676  1.1  christos 
   3677  1.1  christos static void ZSTDv07_checkContinuity(ZSTDv07_DCtx* dctx, const void* dst)
   3678  1.1  christos {
   3679  1.1  christos     if (dst != dctx->previousDstEnd) {   /* not contiguous */
   3680  1.1  christos         dctx->dictEnd = dctx->previousDstEnd;
   3681  1.1  christos         dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
   3682  1.1  christos         dctx->base = dst;
   3683  1.1  christos         dctx->previousDstEnd = dst;
   3684  1.1  christos     }
   3685  1.1  christos }
   3686  1.1  christos 
   3687  1.1  christos 
   3688  1.1  christos static size_t ZSTDv07_decompressBlock_internal(ZSTDv07_DCtx* dctx,
   3689  1.1  christos                             void* dst, size_t dstCapacity,
   3690  1.1  christos                       const void* src, size_t srcSize)
   3691  1.1  christos {   /* blockType == blockCompressed */
   3692  1.1  christos     const BYTE* ip = (const BYTE*)src;
   3693  1.1  christos 
   3694  1.1  christos     if (srcSize >= ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
   3695  1.1  christos 
   3696  1.1  christos     /* Decode literals sub-block */
   3697  1.1  christos     {   size_t const litCSize = ZSTDv07_decodeLiteralsBlock(dctx, src, srcSize);
   3698  1.1  christos         if (ZSTDv07_isError(litCSize)) return litCSize;
   3699  1.1  christos         ip += litCSize;
   3700  1.1  christos         srcSize -= litCSize;
   3701  1.1  christos     }
   3702  1.1  christos     return ZSTDv07_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
   3703  1.1  christos }
   3704  1.1  christos 
   3705  1.1  christos 
   3706  1.1  christos size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,
   3707  1.1  christos                             void* dst, size_t dstCapacity,
   3708  1.1  christos                       const void* src, size_t srcSize)
   3709  1.1  christos {
   3710  1.1  christos     size_t dSize;
   3711  1.1  christos     ZSTDv07_checkContinuity(dctx, dst);
   3712  1.1  christos     dSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
   3713  1.1  christos     dctx->previousDstEnd = (char*)dst + dSize;
   3714  1.1  christos     return dSize;
   3715  1.1  christos }
   3716  1.1  christos 
   3717  1.1  christos 
   3718  1.1  christos /** ZSTDv07_insertBlock() :
   3719  1.1  christos     insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
   3720  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)
   3721  1.1  christos {
   3722  1.1  christos     ZSTDv07_checkContinuity(dctx, blockStart);
   3723  1.1  christos     dctx->previousDstEnd = (const char*)blockStart + blockSize;
   3724  1.1  christos     return blockSize;
   3725  1.1  christos }
   3726  1.1  christos 
   3727  1.1  christos 
   3728  1.1  christos static size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
   3729  1.1  christos {
   3730  1.1  christos     if (length > dstCapacity) return ERROR(dstSize_tooSmall);
   3731  1.1  christos     if (length > 0) {
   3732  1.1  christos         memset(dst, byte, length);
   3733  1.1  christos     }
   3734  1.1  christos     return length;
   3735  1.1  christos }
   3736  1.1  christos 
   3737  1.1  christos 
   3738  1.1  christos /*! ZSTDv07_decompressFrame() :
   3739  1.1  christos *   `dctx` must be properly initialized */
   3740  1.1  christos static size_t ZSTDv07_decompressFrame(ZSTDv07_DCtx* dctx,
   3741  1.1  christos                                  void* dst, size_t dstCapacity,
   3742  1.1  christos                                  const void* src, size_t srcSize)
   3743  1.1  christos {
   3744  1.1  christos     const BYTE* ip = (const BYTE*)src;
   3745  1.1  christos     const BYTE* const iend = ip + srcSize;
   3746  1.1  christos     BYTE* const ostart = (BYTE*)dst;
   3747  1.1  christos     BYTE* const oend = ostart + dstCapacity;
   3748  1.1  christos     BYTE* op = ostart;
   3749  1.1  christos     size_t remainingSize = srcSize;
   3750  1.1  christos 
   3751  1.1  christos     /* check */
   3752  1.1  christos     if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
   3753  1.1  christos 
   3754  1.1  christos     /* Frame Header */
   3755  1.1  christos     {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
   3756  1.1  christos         if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;
   3757  1.1  christos         if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);
   3758  1.1  christos         if (ZSTDv07_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);
   3759  1.1  christos         ip += frameHeaderSize; remainingSize -= frameHeaderSize;
   3760  1.1  christos     }
   3761  1.1  christos 
   3762  1.1  christos     /* Loop on each block */
   3763  1.1  christos     while (1) {
   3764  1.1  christos         size_t decodedSize;
   3765  1.1  christos         blockProperties_t blockProperties;
   3766  1.1  christos         size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, iend-ip, &blockProperties);
   3767  1.1  christos         if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
   3768  1.1  christos 
   3769  1.1  christos         ip += ZSTDv07_blockHeaderSize;
   3770  1.1  christos         remainingSize -= ZSTDv07_blockHeaderSize;
   3771  1.1  christos         if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
   3772  1.1  christos 
   3773  1.1  christos         switch(blockProperties.blockType)
   3774  1.1  christos         {
   3775  1.1  christos         case bt_compressed:
   3776  1.1  christos             decodedSize = ZSTDv07_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
   3777  1.1  christos             break;
   3778  1.1  christos         case bt_raw :
   3779  1.1  christos             decodedSize = ZSTDv07_copyRawBlock(op, oend-op, ip, cBlockSize);
   3780  1.1  christos             break;
   3781  1.1  christos         case bt_rle :
   3782  1.1  christos             decodedSize = ZSTDv07_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);
   3783  1.1  christos             break;
   3784  1.1  christos         case bt_end :
   3785  1.1  christos             /* end of frame */
   3786  1.1  christos             if (remainingSize) return ERROR(srcSize_wrong);
   3787  1.1  christos             decodedSize = 0;
   3788  1.1  christos             break;
   3789  1.1  christos         default:
   3790  1.1  christos             return ERROR(GENERIC);   /* impossible */
   3791  1.1  christos         }
   3792  1.1  christos         if (blockProperties.blockType == bt_end) break;   /* bt_end */
   3793  1.1  christos 
   3794  1.1  christos         if (ZSTDv07_isError(decodedSize)) return decodedSize;
   3795  1.1  christos         if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);
   3796  1.1  christos         op += decodedSize;
   3797  1.1  christos         ip += cBlockSize;
   3798  1.1  christos         remainingSize -= cBlockSize;
   3799  1.1  christos     }
   3800  1.1  christos 
   3801  1.1  christos     return op-ostart;
   3802  1.1  christos }
   3803  1.1  christos 
   3804  1.1  christos 
   3805  1.1  christos /*! ZSTDv07_decompress_usingPreparedDCtx() :
   3806  1.1  christos *   Same as ZSTDv07_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.
   3807  1.1  christos *   It avoids reloading the dictionary each time.
   3808  1.1  christos *   `preparedDCtx` must have been properly initialized using ZSTDv07_decompressBegin_usingDict().
   3809  1.1  christos *   Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */
   3810  1.1  christos static size_t ZSTDv07_decompress_usingPreparedDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* refDCtx,
   3811  1.1  christos                                          void* dst, size_t dstCapacity,
   3812  1.1  christos                                    const void* src, size_t srcSize)
   3813  1.1  christos {
   3814  1.1  christos     ZSTDv07_copyDCtx(dctx, refDCtx);
   3815  1.1  christos     ZSTDv07_checkContinuity(dctx, dst);
   3816  1.1  christos     return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
   3817  1.1  christos }
   3818  1.1  christos 
   3819  1.1  christos 
   3820  1.1  christos size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,
   3821  1.1  christos                                  void* dst, size_t dstCapacity,
   3822  1.1  christos                                  const void* src, size_t srcSize,
   3823  1.1  christos                                  const void* dict, size_t dictSize)
   3824  1.1  christos {
   3825  1.1  christos     ZSTDv07_decompressBegin_usingDict(dctx, dict, dictSize);
   3826  1.1  christos     ZSTDv07_checkContinuity(dctx, dst);
   3827  1.1  christos     return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
   3828  1.1  christos }
   3829  1.1  christos 
   3830  1.1  christos 
   3831  1.1  christos size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   3832  1.1  christos {
   3833  1.1  christos     return ZSTDv07_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
   3834  1.1  christos }
   3835  1.1  christos 
   3836  1.1  christos 
   3837  1.1  christos size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   3838  1.1  christos {
   3839  1.1  christos #if defined(ZSTDv07_HEAPMODE) && (ZSTDv07_HEAPMODE==1)
   3840  1.1  christos     size_t regenSize;
   3841  1.1  christos     ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx();
   3842  1.1  christos     if (dctx==NULL) return ERROR(memory_allocation);
   3843  1.1  christos     regenSize = ZSTDv07_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
   3844  1.1  christos     ZSTDv07_freeDCtx(dctx);
   3845  1.1  christos     return regenSize;
   3846  1.1  christos #else   /* stack mode */
   3847  1.1  christos     ZSTDv07_DCtx dctx;
   3848  1.1  christos     return ZSTDv07_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
   3849  1.1  christos #endif
   3850  1.1  christos }
   3851  1.1  christos 
   3852  1.1  christos /* ZSTD_errorFrameSizeInfoLegacy() :
   3853  1.1  christos    assumes `cSize` and `dBound` are _not_ NULL */
   3854  1.1  christos static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
   3855  1.1  christos {
   3856  1.1  christos     *cSize = ret;
   3857  1.1  christos     *dBound = ZSTD_CONTENTSIZE_ERROR;
   3858  1.1  christos }
   3859  1.1  christos 
   3860  1.1  christos void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
   3861  1.1  christos {
   3862  1.1  christos     const BYTE* ip = (const BYTE*)src;
   3863  1.1  christos     size_t remainingSize = srcSize;
   3864  1.1  christos     size_t nbBlocks = 0;
   3865  1.1  christos 
   3866  1.1  christos     /* check */
   3867  1.1  christos     if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {
   3868  1.1  christos         ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
   3869  1.1  christos         return;
   3870  1.1  christos     }
   3871  1.1  christos 
   3872  1.1  christos     /* Frame Header */
   3873  1.1  christos     {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);
   3874  1.1  christos         if (ZSTDv07_isError(frameHeaderSize)) {
   3875  1.1  christos             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);
   3876  1.1  christos             return;
   3877  1.1  christos         }
   3878  1.1  christos         if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {
   3879  1.1  christos             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
   3880  1.1  christos             return;
   3881  1.1  christos         }
   3882  1.1  christos         if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {
   3883  1.1  christos             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
   3884  1.1  christos             return;
   3885  1.1  christos         }
   3886  1.1  christos         ip += frameHeaderSize; remainingSize -= frameHeaderSize;
   3887  1.1  christos     }
   3888  1.1  christos 
   3889  1.1  christos     /* Loop on each block */
   3890  1.1  christos     while (1) {
   3891  1.1  christos         blockProperties_t blockProperties;
   3892  1.1  christos         size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);
   3893  1.1  christos         if (ZSTDv07_isError(cBlockSize)) {
   3894  1.1  christos             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
   3895  1.1  christos             return;
   3896  1.1  christos         }
   3897  1.1  christos 
   3898  1.1  christos         ip += ZSTDv07_blockHeaderSize;
   3899  1.1  christos         remainingSize -= ZSTDv07_blockHeaderSize;
   3900  1.1  christos 
   3901  1.1  christos         if (blockProperties.blockType == bt_end) break;
   3902  1.1  christos 
   3903  1.1  christos         if (cBlockSize > remainingSize) {
   3904  1.1  christos             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
   3905  1.1  christos             return;
   3906  1.1  christos         }
   3907  1.1  christos 
   3908  1.1  christos         ip += cBlockSize;
   3909  1.1  christos         remainingSize -= cBlockSize;
   3910  1.1  christos         nbBlocks++;
   3911  1.1  christos     }
   3912  1.1  christos 
   3913  1.1  christos     *cSize = ip - (const BYTE*)src;
   3914  1.1  christos     *dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;
   3915  1.1  christos }
   3916  1.1  christos 
   3917  1.1  christos /*_******************************
   3918  1.1  christos *  Streaming Decompression API
   3919  1.1  christos ********************************/
   3920  1.1  christos size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx)
   3921  1.1  christos {
   3922  1.1  christos     return dctx->expected;
   3923  1.1  christos }
   3924  1.1  christos 
   3925  1.1  christos int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx)
   3926  1.1  christos {
   3927  1.1  christos     return dctx->stage == ZSTDds_skipFrame;
   3928  1.1  christos }
   3929  1.1  christos 
   3930  1.1  christos /** ZSTDv07_decompressContinue() :
   3931  1.1  christos *   @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
   3932  1.1  christos *             or an error code, which can be tested using ZSTDv07_isError() */
   3933  1.1  christos size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   3934  1.1  christos {
   3935  1.1  christos     /* Sanity check */
   3936  1.1  christos     if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
   3937  1.1  christos     if (dstCapacity) ZSTDv07_checkContinuity(dctx, dst);
   3938  1.1  christos 
   3939  1.1  christos     switch (dctx->stage)
   3940  1.1  christos     {
   3941  1.1  christos     case ZSTDds_getFrameHeaderSize :
   3942  1.1  christos         if (srcSize != ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */
   3943  1.1  christos         if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {
   3944  1.1  christos             memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);
   3945  1.1  christos             dctx->expected = ZSTDv07_skippableHeaderSize - ZSTDv07_frameHeaderSize_min; /* magic number + skippable frame length */
   3946  1.1  christos             dctx->stage = ZSTDds_decodeSkippableHeader;
   3947  1.1  christos             return 0;
   3948  1.1  christos         }
   3949  1.1  christos         dctx->headerSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);
   3950  1.1  christos         if (ZSTDv07_isError(dctx->headerSize)) return dctx->headerSize;
   3951  1.1  christos         memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);
   3952  1.1  christos         if (dctx->headerSize > ZSTDv07_frameHeaderSize_min) {
   3953  1.1  christos             dctx->expected = dctx->headerSize - ZSTDv07_frameHeaderSize_min;
   3954  1.1  christos             dctx->stage = ZSTDds_decodeFrameHeader;
   3955  1.1  christos             return 0;
   3956  1.1  christos         }
   3957  1.1  christos         dctx->expected = 0;   /* not necessary to copy more */
   3958  1.1  christos 	/* fall-through */
   3959  1.1  christos     case ZSTDds_decodeFrameHeader:
   3960  1.1  christos         {   size_t result;
   3961  1.1  christos             memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);
   3962  1.1  christos             result = ZSTDv07_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
   3963  1.1  christos             if (ZSTDv07_isError(result)) return result;
   3964  1.1  christos             dctx->expected = ZSTDv07_blockHeaderSize;
   3965  1.1  christos             dctx->stage = ZSTDds_decodeBlockHeader;
   3966  1.1  christos             return 0;
   3967  1.1  christos         }
   3968  1.1  christos     case ZSTDds_decodeBlockHeader:
   3969  1.1  christos         {   blockProperties_t bp;
   3970  1.1  christos             size_t const cBlockSize = ZSTDv07_getcBlockSize(src, ZSTDv07_blockHeaderSize, &bp);
   3971  1.1  christos             if (ZSTDv07_isError(cBlockSize)) return cBlockSize;
   3972  1.1  christos             if (bp.blockType == bt_end) {
   3973  1.1  christos                 if (dctx->fParams.checksumFlag) {
   3974  1.1  christos                     U64 const h64 = XXH64_digest(&dctx->xxhState);
   3975  1.1  christos                     U32 const h32 = (U32)(h64>>11) & ((1<<22)-1);
   3976  1.1  christos                     const BYTE* const ip = (const BYTE*)src;
   3977  1.1  christos                     U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16);
   3978  1.1  christos                     if (check32 != h32) return ERROR(checksum_wrong);
   3979  1.1  christos                 }
   3980  1.1  christos                 dctx->expected = 0;
   3981  1.1  christos                 dctx->stage = ZSTDds_getFrameHeaderSize;
   3982  1.1  christos             } else {
   3983  1.1  christos                 dctx->expected = cBlockSize;
   3984  1.1  christos                 dctx->bType = bp.blockType;
   3985  1.1  christos                 dctx->stage = ZSTDds_decompressBlock;
   3986  1.1  christos             }
   3987  1.1  christos             return 0;
   3988  1.1  christos         }
   3989  1.1  christos     case ZSTDds_decompressBlock:
   3990  1.1  christos         {   size_t rSize;
   3991  1.1  christos             switch(dctx->bType)
   3992  1.1  christos             {
   3993  1.1  christos             case bt_compressed:
   3994  1.1  christos                 rSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
   3995  1.1  christos                 break;
   3996  1.1  christos             case bt_raw :
   3997  1.1  christos                 rSize = ZSTDv07_copyRawBlock(dst, dstCapacity, src, srcSize);
   3998  1.1  christos                 break;
   3999  1.1  christos             case bt_rle :
   4000  1.1  christos                 return ERROR(GENERIC);   /* not yet handled */
   4001  1.1  christos                 break;
   4002  1.1  christos             case bt_end :   /* should never happen (filtered at phase 1) */
   4003  1.1  christos                 rSize = 0;
   4004  1.1  christos                 break;
   4005  1.1  christos             default:
   4006  1.1  christos                 return ERROR(GENERIC);   /* impossible */
   4007  1.1  christos             }
   4008  1.1  christos             dctx->stage = ZSTDds_decodeBlockHeader;
   4009  1.1  christos             dctx->expected = ZSTDv07_blockHeaderSize;
   4010  1.1  christos             if (ZSTDv07_isError(rSize)) return rSize;
   4011  1.1  christos             dctx->previousDstEnd = (char*)dst + rSize;
   4012  1.1  christos             if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
   4013  1.1  christos             return rSize;
   4014  1.1  christos         }
   4015  1.1  christos     case ZSTDds_decodeSkippableHeader:
   4016  1.1  christos         {   memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);
   4017  1.1  christos             dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);
   4018  1.1  christos             dctx->stage = ZSTDds_skipFrame;
   4019  1.1  christos             return 0;
   4020  1.1  christos         }
   4021  1.1  christos     case ZSTDds_skipFrame:
   4022  1.1  christos         {   dctx->expected = 0;
   4023  1.1  christos             dctx->stage = ZSTDds_getFrameHeaderSize;
   4024  1.1  christos             return 0;
   4025  1.1  christos         }
   4026  1.1  christos     default:
   4027  1.1  christos         return ERROR(GENERIC);   /* impossible */
   4028  1.1  christos     }
   4029  1.1  christos }
   4030  1.1  christos 
   4031  1.1  christos 
   4032  1.1  christos static size_t ZSTDv07_refDictContent(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
   4033  1.1  christos {
   4034  1.1  christos     dctx->dictEnd = dctx->previousDstEnd;
   4035  1.1  christos     dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
   4036  1.1  christos     dctx->base = dict;
   4037  1.1  christos     dctx->previousDstEnd = (const char*)dict + dictSize;
   4038  1.1  christos     return 0;
   4039  1.1  christos }
   4040  1.1  christos 
   4041  1.1  christos static size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, size_t const dictSize)
   4042  1.1  christos {
   4043  1.1  christos     const BYTE* dictPtr = (const BYTE*)dict;
   4044  1.1  christos     const BYTE* const dictEnd = dictPtr + dictSize;
   4045  1.1  christos 
   4046  1.1  christos     {   size_t const hSize = HUFv07_readDTableX4(dctx->hufTable, dict, dictSize);
   4047  1.1  christos         if (HUFv07_isError(hSize)) return ERROR(dictionary_corrupted);
   4048  1.1  christos         dictPtr += hSize;
   4049  1.1  christos     }
   4050  1.1  christos 
   4051  1.1  christos     {   short offcodeNCount[MaxOff+1];
   4052  1.1  christos         U32 offcodeMaxValue=MaxOff, offcodeLog;
   4053  1.1  christos         size_t const offcodeHeaderSize = FSEv07_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
   4054  1.1  christos         if (FSEv07_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
   4055  1.1  christos         if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
   4056  1.1  christos         { size_t const errorCode = FSEv07_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
   4057  1.1  christos           if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
   4058  1.1  christos         dictPtr += offcodeHeaderSize;
   4059  1.1  christos     }
   4060  1.1  christos 
   4061  1.1  christos     {   short matchlengthNCount[MaxML+1];
   4062  1.1  christos         unsigned matchlengthMaxValue = MaxML, matchlengthLog;
   4063  1.1  christos         size_t const matchlengthHeaderSize = FSEv07_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
   4064  1.1  christos         if (FSEv07_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
   4065  1.1  christos         if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
   4066  1.1  christos         { size_t const errorCode = FSEv07_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
   4067  1.1  christos           if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
   4068  1.1  christos         dictPtr += matchlengthHeaderSize;
   4069  1.1  christos     }
   4070  1.1  christos 
   4071  1.1  christos     {   short litlengthNCount[MaxLL+1];
   4072  1.1  christos         unsigned litlengthMaxValue = MaxLL, litlengthLog;
   4073  1.1  christos         size_t const litlengthHeaderSize = FSEv07_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
   4074  1.1  christos         if (FSEv07_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
   4075  1.1  christos         if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
   4076  1.1  christos         { size_t const errorCode = FSEv07_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
   4077  1.1  christos           if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }
   4078  1.1  christos         dictPtr += litlengthHeaderSize;
   4079  1.1  christos     }
   4080  1.1  christos 
   4081  1.1  christos     if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
   4082  1.1  christos     dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
   4083  1.1  christos     dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
   4084  1.1  christos     dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
   4085  1.1  christos     dictPtr += 12;
   4086  1.1  christos 
   4087  1.1  christos     dctx->litEntropy = dctx->fseEntropy = 1;
   4088  1.1  christos     return dictPtr - (const BYTE*)dict;
   4089  1.1  christos }
   4090  1.1  christos 
   4091  1.1  christos static size_t ZSTDv07_decompress_insertDictionary(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
   4092  1.1  christos {
   4093  1.1  christos     if (dictSize < 8) return ZSTDv07_refDictContent(dctx, dict, dictSize);
   4094  1.1  christos     {   U32 const magic = MEM_readLE32(dict);
   4095  1.1  christos         if (magic != ZSTDv07_DICT_MAGIC) {
   4096  1.1  christos             return ZSTDv07_refDictContent(dctx, dict, dictSize);   /* pure content mode */
   4097  1.1  christos     }   }
   4098  1.1  christos     dctx->dictID = MEM_readLE32((const char*)dict + 4);
   4099  1.1  christos 
   4100  1.1  christos     /* load entropy tables */
   4101  1.1  christos     dict = (const char*)dict + 8;
   4102  1.1  christos     dictSize -= 8;
   4103  1.1  christos     {   size_t const eSize = ZSTDv07_loadEntropy(dctx, dict, dictSize);
   4104  1.1  christos         if (ZSTDv07_isError(eSize)) return ERROR(dictionary_corrupted);
   4105  1.1  christos         dict = (const char*)dict + eSize;
   4106  1.1  christos         dictSize -= eSize;
   4107  1.1  christos     }
   4108  1.1  christos 
   4109  1.1  christos     /* reference dictionary content */
   4110  1.1  christos     return ZSTDv07_refDictContent(dctx, dict, dictSize);
   4111  1.1  christos }
   4112  1.1  christos 
   4113  1.1  christos 
   4114  1.1  christos size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)
   4115  1.1  christos {
   4116  1.1  christos     { size_t const errorCode = ZSTDv07_decompressBegin(dctx);
   4117  1.1  christos       if (ZSTDv07_isError(errorCode)) return errorCode; }
   4118  1.1  christos 
   4119  1.1  christos     if (dict && dictSize) {
   4120  1.1  christos         size_t const errorCode = ZSTDv07_decompress_insertDictionary(dctx, dict, dictSize);
   4121  1.1  christos         if (ZSTDv07_isError(errorCode)) return ERROR(dictionary_corrupted);
   4122  1.1  christos     }
   4123  1.1  christos 
   4124  1.1  christos     return 0;
   4125  1.1  christos }
   4126  1.1  christos 
   4127  1.1  christos 
   4128  1.1  christos struct ZSTDv07_DDict_s {
   4129  1.1  christos     void* dict;
   4130  1.1  christos     size_t dictSize;
   4131  1.1  christos     ZSTDv07_DCtx* refContext;
   4132  1.1  christos };  /* typedef'd tp ZSTDv07_CDict within zstd.h */
   4133  1.1  christos 
   4134  1.1  christos static ZSTDv07_DDict* ZSTDv07_createDDict_advanced(const void* dict, size_t dictSize, ZSTDv07_customMem customMem)
   4135  1.1  christos {
   4136  1.1  christos     if (!customMem.customAlloc && !customMem.customFree)
   4137  1.1  christos         customMem = defaultCustomMem;
   4138  1.1  christos 
   4139  1.1  christos     if (!customMem.customAlloc || !customMem.customFree)
   4140  1.1  christos         return NULL;
   4141  1.1  christos 
   4142  1.1  christos     {   ZSTDv07_DDict* const ddict = (ZSTDv07_DDict*) customMem.customAlloc(customMem.opaque, sizeof(*ddict));
   4143  1.1  christos         void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);
   4144  1.1  christos         ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx_advanced(customMem);
   4145  1.1  christos 
   4146  1.1  christos         if (!dictContent || !ddict || !dctx) {
   4147  1.1  christos             customMem.customFree(customMem.opaque, dictContent);
   4148  1.1  christos             customMem.customFree(customMem.opaque, ddict);
   4149  1.1  christos             customMem.customFree(customMem.opaque, dctx);
   4150  1.1  christos             return NULL;
   4151  1.1  christos         }
   4152  1.1  christos 
   4153  1.1  christos         memcpy(dictContent, dict, dictSize);
   4154  1.1  christos         {   size_t const errorCode = ZSTDv07_decompressBegin_usingDict(dctx, dictContent, dictSize);
   4155  1.1  christos             if (ZSTDv07_isError(errorCode)) {
   4156  1.1  christos                 customMem.customFree(customMem.opaque, dictContent);
   4157  1.1  christos                 customMem.customFree(customMem.opaque, ddict);
   4158  1.1  christos                 customMem.customFree(customMem.opaque, dctx);
   4159  1.1  christos                 return NULL;
   4160  1.1  christos         }   }
   4161  1.1  christos 
   4162  1.1  christos         ddict->dict = dictContent;
   4163  1.1  christos         ddict->dictSize = dictSize;
   4164  1.1  christos         ddict->refContext = dctx;
   4165  1.1  christos         return ddict;
   4166  1.1  christos     }
   4167  1.1  christos }
   4168  1.1  christos 
   4169  1.1  christos /*! ZSTDv07_createDDict() :
   4170  1.1  christos *   Create a digested dictionary, ready to start decompression without startup delay.
   4171  1.1  christos *   `dict` can be released after `ZSTDv07_DDict` creation */
   4172  1.1  christos ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize)
   4173  1.1  christos {
   4174  1.1  christos     ZSTDv07_customMem const allocator = { NULL, NULL, NULL };
   4175  1.1  christos     return ZSTDv07_createDDict_advanced(dict, dictSize, allocator);
   4176  1.1  christos }
   4177  1.1  christos 
   4178  1.1  christos size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)
   4179  1.1  christos {
   4180  1.1  christos     ZSTDv07_freeFunction const cFree = ddict->refContext->customMem.customFree;
   4181  1.1  christos     void* const opaque = ddict->refContext->customMem.opaque;
   4182  1.1  christos     ZSTDv07_freeDCtx(ddict->refContext);
   4183  1.1  christos     cFree(opaque, ddict->dict);
   4184  1.1  christos     cFree(opaque, ddict);
   4185  1.1  christos     return 0;
   4186  1.1  christos }
   4187  1.1  christos 
   4188  1.1  christos /*! ZSTDv07_decompress_usingDDict() :
   4189  1.1  christos *   Decompression using a pre-digested Dictionary
   4190  1.1  christos *   Use dictionary without significant overhead. */
   4191  1.1  christos ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
   4192  1.1  christos                                            void* dst, size_t dstCapacity,
   4193  1.1  christos                                      const void* src, size_t srcSize,
   4194  1.1  christos                                      const ZSTDv07_DDict* ddict)
   4195  1.1  christos {
   4196  1.1  christos     return ZSTDv07_decompress_usingPreparedDCtx(dctx, ddict->refContext,
   4197  1.1  christos                                            dst, dstCapacity,
   4198  1.1  christos                                            src, srcSize);
   4199  1.1  christos }
   4200  1.1  christos /*
   4201  1.1  christos     Buffered version of Zstd compression library
   4202  1.1  christos     Copyright (C) 2015-2016, Yann Collet.
   4203  1.1  christos 
   4204  1.1  christos     BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
   4205  1.1  christos 
   4206  1.1  christos     Redistribution and use in source and binary forms, with or without
   4207  1.1  christos     modification, are permitted provided that the following conditions are
   4208  1.1  christos     met:
   4209  1.1  christos     * Redistributions of source code must retain the above copyright
   4210  1.1  christos     notice, this list of conditions and the following disclaimer.
   4211  1.1  christos     * Redistributions in binary form must reproduce the above
   4212  1.1  christos     copyright notice, this list of conditions and the following disclaimer
   4213  1.1  christos     in the documentation and/or other materials provided with the
   4214  1.1  christos     distribution.
   4215  1.1  christos     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   4216  1.1  christos     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   4217  1.1  christos     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   4218  1.1  christos     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   4219  1.1  christos     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   4220  1.1  christos     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   4221  1.1  christos     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   4222  1.1  christos     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   4223  1.1  christos     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   4224  1.1  christos     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   4225  1.1  christos     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   4226  1.1  christos 
   4227  1.1  christos     You can contact the author at :
   4228  1.1  christos     - zstd homepage : https://facebook.github.io/zstd/
   4229  1.1  christos */
   4230  1.1  christos 
   4231  1.1  christos 
   4232  1.1  christos 
   4233  1.1  christos /*-***************************************************************************
   4234  1.1  christos *  Streaming decompression howto
   4235  1.1  christos *
   4236  1.1  christos *  A ZBUFFv07_DCtx object is required to track streaming operations.
   4237  1.1  christos *  Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.
   4238  1.1  christos *  Use ZBUFFv07_decompressInit() to start a new decompression operation,
   4239  1.1  christos *   or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.
   4240  1.1  christos *  Note that ZBUFFv07_DCtx objects can be re-init multiple times.
   4241  1.1  christos *
   4242  1.1  christos *  Use ZBUFFv07_decompressContinue() repetitively to consume your input.
   4243  1.1  christos *  *srcSizePtr and *dstCapacityPtr can be any size.
   4244  1.1  christos *  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.
   4245  1.1  christos *  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.
   4246  1.1  christos *  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.
   4247  1.1  christos *  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),
   4248  1.1  christos *            or 0 when a frame is completely decoded,
   4249  1.1  christos *            or an error code, which can be tested using ZBUFFv07_isError().
   4250  1.1  christos *
   4251  1.1  christos *  Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()
   4252  1.1  christos *  output : ZBUFFv07_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.
   4253  1.1  christos *  input  : ZBUFFv07_recommendedDInSize == 128KB + 3;
   4254  1.1  christos *           just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .
   4255  1.1  christos * *******************************************************************************/
   4256  1.1  christos 
   4257  1.1  christos typedef enum { ZBUFFds_init, ZBUFFds_loadHeader,
   4258  1.1  christos                ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv07_dStage;
   4259  1.1  christos 
   4260  1.1  christos /* *** Resource management *** */
   4261  1.1  christos struct ZBUFFv07_DCtx_s {
   4262  1.1  christos     ZSTDv07_DCtx* zd;
   4263  1.1  christos     ZSTDv07_frameParams fParams;
   4264  1.1  christos     ZBUFFv07_dStage stage;
   4265  1.1  christos     char*  inBuff;
   4266  1.1  christos     size_t inBuffSize;
   4267  1.1  christos     size_t inPos;
   4268  1.1  christos     char*  outBuff;
   4269  1.1  christos     size_t outBuffSize;
   4270  1.1  christos     size_t outStart;
   4271  1.1  christos     size_t outEnd;
   4272  1.1  christos     size_t blockSize;
   4273  1.1  christos     BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];
   4274  1.1  christos     size_t lhSize;
   4275  1.1  christos     ZSTDv07_customMem customMem;
   4276  1.1  christos };   /* typedef'd to ZBUFFv07_DCtx within "zstd_buffered.h" */
   4277  1.1  christos 
   4278  1.1  christos ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);
   4279  1.1  christos 
   4280  1.1  christos ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)
   4281  1.1  christos {
   4282  1.1  christos     return ZBUFFv07_createDCtx_advanced(defaultCustomMem);
   4283  1.1  christos }
   4284  1.1  christos 
   4285  1.1  christos ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem)
   4286  1.1  christos {
   4287  1.1  christos     ZBUFFv07_DCtx* zbd;
   4288  1.1  christos 
   4289  1.1  christos     if (!customMem.customAlloc && !customMem.customFree)
   4290  1.1  christos         customMem = defaultCustomMem;
   4291  1.1  christos 
   4292  1.1  christos     if (!customMem.customAlloc || !customMem.customFree)
   4293  1.1  christos         return NULL;
   4294  1.1  christos 
   4295  1.1  christos     zbd = (ZBUFFv07_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFFv07_DCtx));
   4296  1.1  christos     if (zbd==NULL) return NULL;
   4297  1.1  christos     memset(zbd, 0, sizeof(ZBUFFv07_DCtx));
   4298  1.1  christos     memcpy(&zbd->customMem, &customMem, sizeof(ZSTDv07_customMem));
   4299  1.1  christos     zbd->zd = ZSTDv07_createDCtx_advanced(customMem);
   4300  1.1  christos     if (zbd->zd == NULL) { ZBUFFv07_freeDCtx(zbd); return NULL; }
   4301  1.1  christos     zbd->stage = ZBUFFds_init;
   4302  1.1  christos     return zbd;
   4303  1.1  christos }
   4304  1.1  christos 
   4305  1.1  christos size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* zbd)
   4306  1.1  christos {
   4307  1.1  christos     if (zbd==NULL) return 0;   /* support free on null */
   4308  1.1  christos     ZSTDv07_freeDCtx(zbd->zd);
   4309  1.1  christos     if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
   4310  1.1  christos     if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
   4311  1.1  christos     zbd->customMem.customFree(zbd->customMem.opaque, zbd);
   4312  1.1  christos     return 0;
   4313  1.1  christos }
   4314  1.1  christos 
   4315  1.1  christos 
   4316  1.1  christos /* *** Initialization *** */
   4317  1.1  christos 
   4318  1.1  christos size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* zbd, const void* dict, size_t dictSize)
   4319  1.1  christos {
   4320  1.1  christos     zbd->stage = ZBUFFds_loadHeader;
   4321  1.1  christos     zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;
   4322  1.1  christos     return ZSTDv07_decompressBegin_usingDict(zbd->zd, dict, dictSize);
   4323  1.1  christos }
   4324  1.1  christos 
   4325  1.1  christos size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd)
   4326  1.1  christos {
   4327  1.1  christos     return ZBUFFv07_decompressInitDictionary(zbd, NULL, 0);
   4328  1.1  christos }
   4329  1.1  christos 
   4330  1.1  christos 
   4331  1.1  christos /* internal util function */
   4332  1.1  christos MEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   4333  1.1  christos {
   4334  1.1  christos     size_t const length = MIN(dstCapacity, srcSize);
   4335  1.1  christos     if (length > 0) {
   4336  1.1  christos         memcpy(dst, src, length);
   4337  1.1  christos     }
   4338  1.1  christos     return length;
   4339  1.1  christos }
   4340  1.1  christos 
   4341  1.1  christos 
   4342  1.1  christos /* *** Decompression *** */
   4343  1.1  christos 
   4344  1.1  christos size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,
   4345  1.1  christos                                 void* dst, size_t* dstCapacityPtr,
   4346  1.1  christos                           const void* src, size_t* srcSizePtr)
   4347  1.1  christos {
   4348  1.1  christos     const char* const istart = (const char*)src;
   4349  1.1  christos     const char* const iend = istart + *srcSizePtr;
   4350  1.1  christos     const char* ip = istart;
   4351  1.1  christos     char* const ostart = (char*)dst;
   4352  1.1  christos     char* const oend = ostart + *dstCapacityPtr;
   4353  1.1  christos     char* op = ostart;
   4354  1.1  christos     U32 notDone = 1;
   4355  1.1  christos 
   4356  1.1  christos     while (notDone) {
   4357  1.1  christos         switch(zbd->stage)
   4358  1.1  christos         {
   4359  1.1  christos         case ZBUFFds_init :
   4360  1.1  christos             return ERROR(init_missing);
   4361  1.1  christos 
   4362  1.1  christos         case ZBUFFds_loadHeader :
   4363  1.1  christos             {   size_t const hSize = ZSTDv07_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);
   4364  1.1  christos                 if (ZSTDv07_isError(hSize)) return hSize;
   4365  1.1  christos                 if (hSize != 0) {
   4366  1.1  christos                     size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */
   4367  1.1  christos                     if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */
   4368  1.1  christos                         if (ip != NULL)
   4369  1.1  christos                             memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
   4370  1.1  christos                         zbd->lhSize += iend-ip;
   4371  1.1  christos                         *dstCapacityPtr = 0;
   4372  1.1  christos                         return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize;   /* remaining header bytes + next block header */
   4373  1.1  christos                     }
   4374  1.1  christos                     memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;
   4375  1.1  christos                     break;
   4376  1.1  christos             }   }
   4377  1.1  christos 
   4378  1.1  christos             /* Consume header */
   4379  1.1  christos             {   size_t const h1Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTDv07_frameHeaderSize_min */
   4380  1.1  christos                 size_t const h1Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);
   4381  1.1  christos                 if (ZSTDv07_isError(h1Result)) return h1Result;
   4382  1.1  christos                 if (h1Size < zbd->lhSize) {   /* long header */
   4383  1.1  christos                     size_t const h2Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
   4384  1.1  christos                     size_t const h2Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);
   4385  1.1  christos                     if (ZSTDv07_isError(h2Result)) return h2Result;
   4386  1.1  christos             }   }
   4387  1.1  christos 
   4388  1.1  christos             zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTDv07_WINDOWLOG_ABSOLUTEMIN);
   4389  1.1  christos 
   4390  1.1  christos             /* Frame header instruct buffer sizes */
   4391  1.1  christos             {   size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTDv07_BLOCKSIZE_ABSOLUTEMAX);
   4392  1.1  christos                 zbd->blockSize = blockSize;
   4393  1.1  christos                 if (zbd->inBuffSize < blockSize) {
   4394  1.1  christos                     zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
   4395  1.1  christos                     zbd->inBuffSize = blockSize;
   4396  1.1  christos                     zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);
   4397  1.1  christos                     if (zbd->inBuff == NULL) return ERROR(memory_allocation);
   4398  1.1  christos                 }
   4399  1.1  christos                 {   size_t const neededOutSize = zbd->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
   4400  1.1  christos                     if (zbd->outBuffSize < neededOutSize) {
   4401  1.1  christos                         zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
   4402  1.1  christos                         zbd->outBuffSize = neededOutSize;
   4403  1.1  christos                         zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);
   4404  1.1  christos                         if (zbd->outBuff == NULL) return ERROR(memory_allocation);
   4405  1.1  christos             }   }   }
   4406  1.1  christos             zbd->stage = ZBUFFds_read;
   4407  1.1  christos             /* pass-through */
   4408  1.1  christos 	    /* fall-through */
   4409  1.1  christos         case ZBUFFds_read:
   4410  1.1  christos             {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
   4411  1.1  christos                 if (neededInSize==0) {  /* end of frame */
   4412  1.1  christos                     zbd->stage = ZBUFFds_init;
   4413  1.1  christos                     notDone = 0;
   4414  1.1  christos                     break;
   4415  1.1  christos                 }
   4416  1.1  christos                 if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */
   4417  1.1  christos                     const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);
   4418  1.1  christos                     size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,
   4419  1.1  christos                         zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),
   4420  1.1  christos                         ip, neededInSize);
   4421  1.1  christos                     if (ZSTDv07_isError(decodedSize)) return decodedSize;
   4422  1.1  christos                     ip += neededInSize;
   4423  1.1  christos                     if (!decodedSize && !isSkipFrame) break;   /* this was just a header */
   4424  1.1  christos                     zbd->outEnd = zbd->outStart +  decodedSize;
   4425  1.1  christos                     zbd->stage = ZBUFFds_flush;
   4426  1.1  christos                     break;
   4427  1.1  christos                 }
   4428  1.1  christos                 if (ip==iend) { notDone = 0; break; }   /* no more input */
   4429  1.1  christos                 zbd->stage = ZBUFFds_load;
   4430  1.1  christos             }
   4431  1.1  christos 	    /* fall-through */
   4432  1.1  christos         case ZBUFFds_load:
   4433  1.1  christos             {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
   4434  1.1  christos                 size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */
   4435  1.1  christos                 size_t loadedSize;
   4436  1.1  christos                 if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */
   4437  1.1  christos                 loadedSize = ZBUFFv07_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);
   4438  1.1  christos                 ip += loadedSize;
   4439  1.1  christos                 zbd->inPos += loadedSize;
   4440  1.1  christos                 if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */
   4441  1.1  christos 
   4442  1.1  christos                 /* decode loaded input */
   4443  1.1  christos                 {  const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);
   4444  1.1  christos                    size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,
   4445  1.1  christos                         zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,
   4446  1.1  christos                         zbd->inBuff, neededInSize);
   4447  1.1  christos                     if (ZSTDv07_isError(decodedSize)) return decodedSize;
   4448  1.1  christos                     zbd->inPos = 0;   /* input is consumed */
   4449  1.1  christos                     if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */
   4450  1.1  christos                     zbd->outEnd = zbd->outStart +  decodedSize;
   4451  1.1  christos                     zbd->stage = ZBUFFds_flush;
   4452  1.1  christos                     /* break; */
   4453  1.1  christos                     /* pass-through */
   4454  1.1  christos                 }
   4455  1.1  christos 	    }
   4456  1.1  christos 	    /* fall-through */
   4457  1.1  christos         case ZBUFFds_flush:
   4458  1.1  christos             {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;
   4459  1.1  christos                 size_t const flushedSize = ZBUFFv07_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);
   4460  1.1  christos                 op += flushedSize;
   4461  1.1  christos                 zbd->outStart += flushedSize;
   4462  1.1  christos                 if (flushedSize == toFlushSize) {
   4463  1.1  christos                     zbd->stage = ZBUFFds_read;
   4464  1.1  christos                     if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)
   4465  1.1  christos                         zbd->outStart = zbd->outEnd = 0;
   4466  1.1  christos                     break;
   4467  1.1  christos                 }
   4468  1.1  christos                 /* cannot flush everything */
   4469  1.1  christos                 notDone = 0;
   4470  1.1  christos                 break;
   4471  1.1  christos             }
   4472  1.1  christos         default: return ERROR(GENERIC);   /* impossible */
   4473  1.1  christos     }   }
   4474  1.1  christos 
   4475  1.1  christos     /* result */
   4476  1.1  christos     *srcSizePtr = ip-istart;
   4477  1.1  christos     *dstCapacityPtr = op-ostart;
   4478  1.1  christos     {   size_t nextSrcSizeHint = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);
   4479  1.1  christos         nextSrcSizeHint -= zbd->inPos;   /* already loaded*/
   4480  1.1  christos         return nextSrcSizeHint;
   4481  1.1  christos     }
   4482  1.1  christos }
   4483  1.1  christos 
   4484  1.1  christos 
   4485  1.1  christos 
   4486  1.1  christos /* *************************************
   4487  1.1  christos *  Tool functions
   4488  1.1  christos ***************************************/
   4489  1.1  christos size_t ZBUFFv07_recommendedDInSize(void)  { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + ZSTDv07_blockHeaderSize /* block header size*/ ; }
   4490  1.1  christos size_t ZBUFFv07_recommendedDOutSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; }
   4491