1*0c16b537SWarner Losh /* 2*0c16b537SWarner Losh * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3*0c16b537SWarner Losh * All rights reserved. 4*0c16b537SWarner Losh * 5*0c16b537SWarner Losh * This source code is licensed under both the BSD-style license (found in the 6*0c16b537SWarner Losh * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*0c16b537SWarner Losh * in the COPYING file in the root directory of this source tree). 8*0c16b537SWarner Losh * You may select, at your option, one of the above-listed licenses. 9*0c16b537SWarner Losh */ 10*0c16b537SWarner Losh 11*0c16b537SWarner Losh 12*0c16b537SWarner Losh /*- Dependencies -*/ 13*0c16b537SWarner Losh #include "zstd_v04.h" 14*0c16b537SWarner Losh #include "error_private.h" 15*0c16b537SWarner Losh 16*0c16b537SWarner Losh 17*0c16b537SWarner Losh /* ****************************************************************** 18*0c16b537SWarner Losh mem.h 19*0c16b537SWarner Losh low-level memory access routines 20*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 21*0c16b537SWarner Losh 22*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 23*0c16b537SWarner Losh 24*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 25*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 26*0c16b537SWarner Losh met: 27*0c16b537SWarner Losh 28*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 29*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 30*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 31*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 32*0c16b537SWarner Losh in the documentation and/or other materials provided with the 33*0c16b537SWarner Losh distribution. 34*0c16b537SWarner Losh 35*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46*0c16b537SWarner Losh 47*0c16b537SWarner Losh You can contact the author at : 48*0c16b537SWarner Losh - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy 49*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 50*0c16b537SWarner Losh ****************************************************************** */ 51*0c16b537SWarner Losh #ifndef MEM_H_MODULE 52*0c16b537SWarner Losh #define MEM_H_MODULE 53*0c16b537SWarner Losh 54*0c16b537SWarner Losh #if defined (__cplusplus) 55*0c16b537SWarner Losh extern "C" { 56*0c16b537SWarner Losh #endif 57*0c16b537SWarner Losh 58*0c16b537SWarner Losh /****************************************** 59*0c16b537SWarner Losh * Includes 60*0c16b537SWarner Losh ******************************************/ 61*0c16b537SWarner Losh #include <stddef.h> /* size_t, ptrdiff_t */ 62*0c16b537SWarner Losh #include <string.h> /* memcpy */ 63*0c16b537SWarner Losh 64*0c16b537SWarner Losh 65*0c16b537SWarner Losh /****************************************** 66*0c16b537SWarner Losh * Compiler-specific 67*0c16b537SWarner Losh ******************************************/ 68*0c16b537SWarner Losh #if defined(_MSC_VER) /* Visual Studio */ 69*0c16b537SWarner Losh # include <stdlib.h> /* _byteswap_ulong */ 70*0c16b537SWarner Losh # include <intrin.h> /* _byteswap_* */ 71*0c16b537SWarner Losh #endif 72*0c16b537SWarner Losh #if defined(__GNUC__) 73*0c16b537SWarner Losh # define MEM_STATIC static __attribute__((unused)) 74*0c16b537SWarner Losh #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 75*0c16b537SWarner Losh # define MEM_STATIC static inline 76*0c16b537SWarner Losh #elif defined(_MSC_VER) 77*0c16b537SWarner Losh # define MEM_STATIC static __inline 78*0c16b537SWarner Losh #else 79*0c16b537SWarner Losh # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ 80*0c16b537SWarner Losh #endif 81*0c16b537SWarner Losh 82*0c16b537SWarner Losh 83*0c16b537SWarner Losh /**************************************************************** 84*0c16b537SWarner Losh * Basic Types 85*0c16b537SWarner Losh *****************************************************************/ 86*0c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 87*0c16b537SWarner Losh # include <stdint.h> 88*0c16b537SWarner Losh typedef uint8_t BYTE; 89*0c16b537SWarner Losh typedef uint16_t U16; 90*0c16b537SWarner Losh typedef int16_t S16; 91*0c16b537SWarner Losh typedef uint32_t U32; 92*0c16b537SWarner Losh typedef int32_t S32; 93*0c16b537SWarner Losh typedef uint64_t U64; 94*0c16b537SWarner Losh typedef int64_t S64; 95*0c16b537SWarner Losh #else 96*0c16b537SWarner Losh typedef unsigned char BYTE; 97*0c16b537SWarner Losh typedef unsigned short U16; 98*0c16b537SWarner Losh typedef signed short S16; 99*0c16b537SWarner Losh typedef unsigned int U32; 100*0c16b537SWarner Losh typedef signed int S32; 101*0c16b537SWarner Losh typedef unsigned long long U64; 102*0c16b537SWarner Losh typedef signed long long S64; 103*0c16b537SWarner Losh #endif 104*0c16b537SWarner Losh 105*0c16b537SWarner Losh 106*0c16b537SWarner Losh /**************************************************************** 107*0c16b537SWarner Losh * Memory I/O 108*0c16b537SWarner Losh *****************************************************************/ 109*0c16b537SWarner Losh /* MEM_FORCE_MEMORY_ACCESS 110*0c16b537SWarner Losh * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. 111*0c16b537SWarner Losh * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. 112*0c16b537SWarner Losh * The below switch allow to select different access method for improved performance. 113*0c16b537SWarner Losh * Method 0 (default) : use `memcpy()`. Safe and portable. 114*0c16b537SWarner Losh * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). 115*0c16b537SWarner Losh * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. 116*0c16b537SWarner Losh * Method 2 : direct access. This method is portable but violate C standard. 117*0c16b537SWarner Losh * It can generate buggy code on targets generating assembly depending on alignment. 118*0c16b537SWarner Losh * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) 119*0c16b537SWarner Losh * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. 120*0c16b537SWarner Losh * Prefer these methods in priority order (0 > 1 > 2) 121*0c16b537SWarner Losh */ 122*0c16b537SWarner Losh #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ 123*0c16b537SWarner Losh # if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) 124*0c16b537SWarner Losh # define MEM_FORCE_MEMORY_ACCESS 2 125*0c16b537SWarner Losh # elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ 126*0c16b537SWarner Losh (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) 127*0c16b537SWarner Losh # define MEM_FORCE_MEMORY_ACCESS 1 128*0c16b537SWarner Losh # endif 129*0c16b537SWarner Losh #endif 130*0c16b537SWarner Losh 131*0c16b537SWarner Losh MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; } 132*0c16b537SWarner Losh MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; } 133*0c16b537SWarner Losh 134*0c16b537SWarner Losh MEM_STATIC unsigned MEM_isLittleEndian(void) 135*0c16b537SWarner Losh { 136*0c16b537SWarner Losh const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ 137*0c16b537SWarner Losh return one.c[0]; 138*0c16b537SWarner Losh } 139*0c16b537SWarner Losh 140*0c16b537SWarner Losh #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2) 141*0c16b537SWarner Losh 142*0c16b537SWarner Losh /* violates C standard on structure alignment. 143*0c16b537SWarner Losh Only use if no other choice to achieve best performance on target platform */ 144*0c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; } 145*0c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; } 146*0c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; } 147*0c16b537SWarner Losh 148*0c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } 149*0c16b537SWarner Losh 150*0c16b537SWarner Losh #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1) 151*0c16b537SWarner Losh 152*0c16b537SWarner Losh /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ 153*0c16b537SWarner Losh /* currently only defined for gcc and icc */ 154*0c16b537SWarner Losh typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign; 155*0c16b537SWarner Losh 156*0c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } 157*0c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } 158*0c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; } 159*0c16b537SWarner Losh 160*0c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } 161*0c16b537SWarner Losh 162*0c16b537SWarner Losh #else 163*0c16b537SWarner Losh 164*0c16b537SWarner Losh /* default method, safe and standard. 165*0c16b537SWarner Losh can sometimes prove slower */ 166*0c16b537SWarner Losh 167*0c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr) 168*0c16b537SWarner Losh { 169*0c16b537SWarner Losh U16 val; memcpy(&val, memPtr, sizeof(val)); return val; 170*0c16b537SWarner Losh } 171*0c16b537SWarner Losh 172*0c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr) 173*0c16b537SWarner Losh { 174*0c16b537SWarner Losh U32 val; memcpy(&val, memPtr, sizeof(val)); return val; 175*0c16b537SWarner Losh } 176*0c16b537SWarner Losh 177*0c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr) 178*0c16b537SWarner Losh { 179*0c16b537SWarner Losh U64 val; memcpy(&val, memPtr, sizeof(val)); return val; 180*0c16b537SWarner Losh } 181*0c16b537SWarner Losh 182*0c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) 183*0c16b537SWarner Losh { 184*0c16b537SWarner Losh memcpy(memPtr, &value, sizeof(value)); 185*0c16b537SWarner Losh } 186*0c16b537SWarner Losh 187*0c16b537SWarner Losh #endif // MEM_FORCE_MEMORY_ACCESS 188*0c16b537SWarner Losh 189*0c16b537SWarner Losh 190*0c16b537SWarner Losh MEM_STATIC U16 MEM_readLE16(const void* memPtr) 191*0c16b537SWarner Losh { 192*0c16b537SWarner Losh if (MEM_isLittleEndian()) 193*0c16b537SWarner Losh return MEM_read16(memPtr); 194*0c16b537SWarner Losh else 195*0c16b537SWarner Losh { 196*0c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr; 197*0c16b537SWarner Losh return (U16)(p[0] + (p[1]<<8)); 198*0c16b537SWarner Losh } 199*0c16b537SWarner Losh } 200*0c16b537SWarner Losh 201*0c16b537SWarner Losh MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) 202*0c16b537SWarner Losh { 203*0c16b537SWarner Losh if (MEM_isLittleEndian()) 204*0c16b537SWarner Losh { 205*0c16b537SWarner Losh MEM_write16(memPtr, val); 206*0c16b537SWarner Losh } 207*0c16b537SWarner Losh else 208*0c16b537SWarner Losh { 209*0c16b537SWarner Losh BYTE* p = (BYTE*)memPtr; 210*0c16b537SWarner Losh p[0] = (BYTE)val; 211*0c16b537SWarner Losh p[1] = (BYTE)(val>>8); 212*0c16b537SWarner Losh } 213*0c16b537SWarner Losh } 214*0c16b537SWarner Losh 215*0c16b537SWarner Losh MEM_STATIC U32 MEM_readLE32(const void* memPtr) 216*0c16b537SWarner Losh { 217*0c16b537SWarner Losh if (MEM_isLittleEndian()) 218*0c16b537SWarner Losh return MEM_read32(memPtr); 219*0c16b537SWarner Losh else 220*0c16b537SWarner Losh { 221*0c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr; 222*0c16b537SWarner Losh return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24)); 223*0c16b537SWarner Losh } 224*0c16b537SWarner Losh } 225*0c16b537SWarner Losh 226*0c16b537SWarner Losh 227*0c16b537SWarner Losh MEM_STATIC U64 MEM_readLE64(const void* memPtr) 228*0c16b537SWarner Losh { 229*0c16b537SWarner Losh if (MEM_isLittleEndian()) 230*0c16b537SWarner Losh return MEM_read64(memPtr); 231*0c16b537SWarner Losh else 232*0c16b537SWarner Losh { 233*0c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr; 234*0c16b537SWarner Losh return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24) 235*0c16b537SWarner Losh + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56)); 236*0c16b537SWarner Losh } 237*0c16b537SWarner Losh } 238*0c16b537SWarner Losh 239*0c16b537SWarner Losh 240*0c16b537SWarner Losh MEM_STATIC size_t MEM_readLEST(const void* memPtr) 241*0c16b537SWarner Losh { 242*0c16b537SWarner Losh if (MEM_32bits()) 243*0c16b537SWarner Losh return (size_t)MEM_readLE32(memPtr); 244*0c16b537SWarner Losh else 245*0c16b537SWarner Losh return (size_t)MEM_readLE64(memPtr); 246*0c16b537SWarner Losh } 247*0c16b537SWarner Losh 248*0c16b537SWarner Losh 249*0c16b537SWarner Losh #if defined (__cplusplus) 250*0c16b537SWarner Losh } 251*0c16b537SWarner Losh #endif 252*0c16b537SWarner Losh 253*0c16b537SWarner Losh #endif /* MEM_H_MODULE */ 254*0c16b537SWarner Losh 255*0c16b537SWarner Losh /* 256*0c16b537SWarner Losh zstd - standard compression library 257*0c16b537SWarner Losh Header File for static linking only 258*0c16b537SWarner Losh Copyright (C) 2014-2015, Yann Collet. 259*0c16b537SWarner Losh 260*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 261*0c16b537SWarner Losh 262*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 263*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 264*0c16b537SWarner Losh met: 265*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 266*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 267*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 268*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 269*0c16b537SWarner Losh in the documentation and/or other materials provided with the 270*0c16b537SWarner Losh distribution. 271*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 273*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 274*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 275*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 276*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 277*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 278*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 279*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 280*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 281*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282*0c16b537SWarner Losh 283*0c16b537SWarner Losh You can contact the author at : 284*0c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd 285*0c16b537SWarner Losh - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c 286*0c16b537SWarner Losh */ 287*0c16b537SWarner Losh #ifndef ZSTD_STATIC_H 288*0c16b537SWarner Losh #define ZSTD_STATIC_H 289*0c16b537SWarner Losh 290*0c16b537SWarner Losh /* The objects defined into this file shall be considered experimental. 291*0c16b537SWarner Losh * They are not considered stable, as their prototype may change in the future. 292*0c16b537SWarner Losh * You can use them for tests, provide feedback, or if you can endure risks of future changes. 293*0c16b537SWarner Losh */ 294*0c16b537SWarner Losh 295*0c16b537SWarner Losh #if defined (__cplusplus) 296*0c16b537SWarner Losh extern "C" { 297*0c16b537SWarner Losh #endif 298*0c16b537SWarner Losh 299*0c16b537SWarner Losh /* ************************************* 300*0c16b537SWarner Losh * Types 301*0c16b537SWarner Losh ***************************************/ 302*0c16b537SWarner Losh #define ZSTD_WINDOWLOG_MAX 26 303*0c16b537SWarner Losh #define ZSTD_WINDOWLOG_MIN 18 304*0c16b537SWarner Losh #define ZSTD_WINDOWLOG_ABSOLUTEMIN 11 305*0c16b537SWarner Losh #define ZSTD_CONTENTLOG_MAX (ZSTD_WINDOWLOG_MAX+1) 306*0c16b537SWarner Losh #define ZSTD_CONTENTLOG_MIN 4 307*0c16b537SWarner Losh #define ZSTD_HASHLOG_MAX 28 308*0c16b537SWarner Losh #define ZSTD_HASHLOG_MIN 4 309*0c16b537SWarner Losh #define ZSTD_SEARCHLOG_MAX (ZSTD_CONTENTLOG_MAX-1) 310*0c16b537SWarner Losh #define ZSTD_SEARCHLOG_MIN 1 311*0c16b537SWarner Losh #define ZSTD_SEARCHLENGTH_MAX 7 312*0c16b537SWarner Losh #define ZSTD_SEARCHLENGTH_MIN 4 313*0c16b537SWarner Losh 314*0c16b537SWarner Losh /** from faster to stronger */ 315*0c16b537SWarner Losh typedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2 } ZSTD_strategy; 316*0c16b537SWarner Losh 317*0c16b537SWarner Losh typedef struct 318*0c16b537SWarner Losh { 319*0c16b537SWarner Losh U64 srcSize; /* optional : tells how much bytes are present in the frame. Use 0 if not known. */ 320*0c16b537SWarner Losh U32 windowLog; /* largest match distance : larger == more compression, more memory needed during decompression */ 321*0c16b537SWarner Losh U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */ 322*0c16b537SWarner Losh U32 hashLog; /* dispatch table : larger == more memory, faster */ 323*0c16b537SWarner Losh U32 searchLog; /* nb of searches : larger == more compression, slower */ 324*0c16b537SWarner Losh U32 searchLength; /* size of matches : larger == faster decompression, sometimes less compression */ 325*0c16b537SWarner Losh ZSTD_strategy strategy; 326*0c16b537SWarner Losh } ZSTD_parameters; 327*0c16b537SWarner Losh 328*0c16b537SWarner Losh typedef ZSTDv04_Dctx ZSTD_DCtx; 329*0c16b537SWarner Losh 330*0c16b537SWarner Losh /* ************************************* 331*0c16b537SWarner Losh * Advanced functions 332*0c16b537SWarner Losh ***************************************/ 333*0c16b537SWarner Losh /** ZSTD_decompress_usingDict 334*0c16b537SWarner Losh * Same as ZSTD_decompressDCtx, using a Dictionary content as prefix 335*0c16b537SWarner Losh * Note : dict can be NULL, in which case, it's equivalent to ZSTD_decompressDCtx() */ 336*0c16b537SWarner Losh static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx, 337*0c16b537SWarner Losh void* dst, size_t maxDstSize, 338*0c16b537SWarner Losh const void* src, size_t srcSize, 339*0c16b537SWarner Losh const void* dict,size_t dictSize); 340*0c16b537SWarner Losh 341*0c16b537SWarner Losh 342*0c16b537SWarner Losh /* ************************************** 343*0c16b537SWarner Losh * Streaming functions (direct mode) 344*0c16b537SWarner Losh ****************************************/ 345*0c16b537SWarner Losh static size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx); 346*0c16b537SWarner Losh static size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize); 347*0c16b537SWarner Losh static void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize); 348*0c16b537SWarner Losh 349*0c16b537SWarner Losh static size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); 350*0c16b537SWarner Losh static size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); 351*0c16b537SWarner Losh 352*0c16b537SWarner Losh /** 353*0c16b537SWarner Losh Streaming decompression, bufferless mode 354*0c16b537SWarner Losh 355*0c16b537SWarner Losh A ZSTD_DCtx object is required to track streaming operations. 356*0c16b537SWarner Losh Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. 357*0c16b537SWarner Losh A ZSTD_DCtx object can be re-used multiple times. Use ZSTD_resetDCtx() to return to fresh status. 358*0c16b537SWarner Losh 359*0c16b537SWarner Losh First operation is to retrieve frame parameters, using ZSTD_getFrameParams(). 360*0c16b537SWarner Losh This function doesn't consume its input. It needs enough input data to properly decode the frame header. 361*0c16b537SWarner Losh Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding. 362*0c16b537SWarner Losh Result : 0 when successful, it means the ZSTD_parameters structure has been filled. 363*0c16b537SWarner Losh >0 : means there is not enough data into src. Provides the expected size to successfully decode header. 364*0c16b537SWarner Losh errorCode, which can be tested using ZSTD_isError() (For example, if it's not a ZSTD header) 365*0c16b537SWarner Losh 366*0c16b537SWarner Losh Then, you can optionally insert a dictionary. 367*0c16b537SWarner Losh This operation must mimic the compressor behavior, otherwise decompression will fail or be corrupted. 368*0c16b537SWarner Losh 369*0c16b537SWarner Losh Then it's possible to start decompression. 370*0c16b537SWarner Losh Use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. 371*0c16b537SWarner Losh ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). 372*0c16b537SWarner Losh ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail. 373*0c16b537SWarner Losh ZSTD_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog). 374*0c16b537SWarner Losh They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible. 375*0c16b537SWarner Losh 376*0c16b537SWarner Losh @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst'. 377*0c16b537SWarner Losh It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. 378*0c16b537SWarner Losh 379*0c16b537SWarner Losh A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. 380*0c16b537SWarner Losh Context can then be reset to start a new decompression. 381*0c16b537SWarner Losh */ 382*0c16b537SWarner Losh 383*0c16b537SWarner Losh 384*0c16b537SWarner Losh #if defined (__cplusplus) 385*0c16b537SWarner Losh } 386*0c16b537SWarner Losh #endif 387*0c16b537SWarner Losh 388*0c16b537SWarner Losh 389*0c16b537SWarner Losh #endif /* ZSTD_STATIC_H */ 390*0c16b537SWarner Losh 391*0c16b537SWarner Losh 392*0c16b537SWarner Losh /* 393*0c16b537SWarner Losh zstd_internal - common functions to include 394*0c16b537SWarner Losh Header File for include 395*0c16b537SWarner Losh Copyright (C) 2014-2015, Yann Collet. 396*0c16b537SWarner Losh 397*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 398*0c16b537SWarner Losh 399*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 400*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 401*0c16b537SWarner Losh met: 402*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 403*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 404*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 405*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 406*0c16b537SWarner Losh in the documentation and/or other materials provided with the 407*0c16b537SWarner Losh distribution. 408*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 409*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 410*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 411*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 412*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 413*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 414*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 415*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 416*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 417*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 418*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 419*0c16b537SWarner Losh 420*0c16b537SWarner Losh You can contact the author at : 421*0c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd 422*0c16b537SWarner Losh - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c 423*0c16b537SWarner Losh */ 424*0c16b537SWarner Losh #ifndef ZSTD_CCOMMON_H_MODULE 425*0c16b537SWarner Losh #define ZSTD_CCOMMON_H_MODULE 426*0c16b537SWarner Losh 427*0c16b537SWarner Losh #if defined (__cplusplus) 428*0c16b537SWarner Losh extern "C" { 429*0c16b537SWarner Losh #endif 430*0c16b537SWarner Losh 431*0c16b537SWarner Losh /* ************************************* 432*0c16b537SWarner Losh * Common macros 433*0c16b537SWarner Losh ***************************************/ 434*0c16b537SWarner Losh #define MIN(a,b) ((a)<(b) ? (a) : (b)) 435*0c16b537SWarner Losh #define MAX(a,b) ((a)>(b) ? (a) : (b)) 436*0c16b537SWarner Losh 437*0c16b537SWarner Losh 438*0c16b537SWarner Losh /* ************************************* 439*0c16b537SWarner Losh * Common constants 440*0c16b537SWarner Losh ***************************************/ 441*0c16b537SWarner Losh #define ZSTD_MAGICNUMBER 0xFD2FB524 /* v0.4 */ 442*0c16b537SWarner Losh 443*0c16b537SWarner Losh #define KB *(1 <<10) 444*0c16b537SWarner Losh #define MB *(1 <<20) 445*0c16b537SWarner Losh #define GB *(1U<<30) 446*0c16b537SWarner Losh 447*0c16b537SWarner Losh #define BLOCKSIZE (128 KB) /* define, for static allocation */ 448*0c16b537SWarner Losh 449*0c16b537SWarner Losh static const size_t ZSTD_blockHeaderSize = 3; 450*0c16b537SWarner Losh static const size_t ZSTD_frameHeaderSize_min = 5; 451*0c16b537SWarner Losh #define ZSTD_frameHeaderSize_max 5 /* define, for static allocation */ 452*0c16b537SWarner Losh 453*0c16b537SWarner Losh #define BIT7 128 454*0c16b537SWarner Losh #define BIT6 64 455*0c16b537SWarner Losh #define BIT5 32 456*0c16b537SWarner Losh #define BIT4 16 457*0c16b537SWarner Losh #define BIT1 2 458*0c16b537SWarner Losh #define BIT0 1 459*0c16b537SWarner Losh 460*0c16b537SWarner Losh #define IS_RAW BIT0 461*0c16b537SWarner Losh #define IS_RLE BIT1 462*0c16b537SWarner Losh 463*0c16b537SWarner Losh #define MINMATCH 4 464*0c16b537SWarner Losh #define REPCODE_STARTVALUE 4 465*0c16b537SWarner Losh 466*0c16b537SWarner Losh #define MLbits 7 467*0c16b537SWarner Losh #define LLbits 6 468*0c16b537SWarner Losh #define Offbits 5 469*0c16b537SWarner Losh #define MaxML ((1<<MLbits) - 1) 470*0c16b537SWarner Losh #define MaxLL ((1<<LLbits) - 1) 471*0c16b537SWarner Losh #define MaxOff ((1<<Offbits)- 1) 472*0c16b537SWarner Losh #define MLFSELog 10 473*0c16b537SWarner Losh #define LLFSELog 10 474*0c16b537SWarner Losh #define OffFSELog 9 475*0c16b537SWarner Losh #define MaxSeq MAX(MaxLL, MaxML) 476*0c16b537SWarner Losh 477*0c16b537SWarner Losh #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) 478*0c16b537SWarner Losh #define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE) 479*0c16b537SWarner Losh 480*0c16b537SWarner Losh typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; 481*0c16b537SWarner Losh 482*0c16b537SWarner Losh 483*0c16b537SWarner Losh /* ****************************************** 484*0c16b537SWarner Losh * Shared functions to include for inlining 485*0c16b537SWarner Losh ********************************************/ 486*0c16b537SWarner Losh static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } 487*0c16b537SWarner Losh 488*0c16b537SWarner Losh #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } 489*0c16b537SWarner Losh 490*0c16b537SWarner Losh /*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */ 491*0c16b537SWarner Losh static void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length) 492*0c16b537SWarner Losh { 493*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)src; 494*0c16b537SWarner Losh BYTE* op = (BYTE*)dst; 495*0c16b537SWarner Losh BYTE* const oend = op + length; 496*0c16b537SWarner Losh do 497*0c16b537SWarner Losh COPY8(op, ip) 498*0c16b537SWarner Losh while (op < oend); 499*0c16b537SWarner Losh } 500*0c16b537SWarner Losh 501*0c16b537SWarner Losh 502*0c16b537SWarner Losh #if defined (__cplusplus) 503*0c16b537SWarner Losh } 504*0c16b537SWarner Losh #endif 505*0c16b537SWarner Losh 506*0c16b537SWarner Losh 507*0c16b537SWarner Losh /* ****************************************************************** 508*0c16b537SWarner Losh FSE : Finite State Entropy coder 509*0c16b537SWarner Losh header file 510*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 511*0c16b537SWarner Losh 512*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 513*0c16b537SWarner Losh 514*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 515*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 516*0c16b537SWarner Losh met: 517*0c16b537SWarner Losh 518*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 519*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 520*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 521*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 522*0c16b537SWarner Losh in the documentation and/or other materials provided with the 523*0c16b537SWarner Losh distribution. 524*0c16b537SWarner Losh 525*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 526*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 527*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 528*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 529*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 530*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 531*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 532*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 533*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 534*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 535*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 536*0c16b537SWarner Losh 537*0c16b537SWarner Losh You can contact the author at : 538*0c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 539*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 540*0c16b537SWarner Losh ****************************************************************** */ 541*0c16b537SWarner Losh #ifndef FSE_H 542*0c16b537SWarner Losh #define FSE_H 543*0c16b537SWarner Losh 544*0c16b537SWarner Losh #if defined (__cplusplus) 545*0c16b537SWarner Losh extern "C" { 546*0c16b537SWarner Losh #endif 547*0c16b537SWarner Losh 548*0c16b537SWarner Losh 549*0c16b537SWarner Losh /* ***************************************** 550*0c16b537SWarner Losh * Includes 551*0c16b537SWarner Losh ******************************************/ 552*0c16b537SWarner Losh #include <stddef.h> /* size_t, ptrdiff_t */ 553*0c16b537SWarner Losh 554*0c16b537SWarner Losh 555*0c16b537SWarner Losh /* ***************************************** 556*0c16b537SWarner Losh * FSE simple functions 557*0c16b537SWarner Losh ******************************************/ 558*0c16b537SWarner Losh static size_t FSE_decompress(void* dst, size_t maxDstSize, 559*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize); 560*0c16b537SWarner Losh /*! 561*0c16b537SWarner Losh FSE_decompress(): 562*0c16b537SWarner Losh Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', 563*0c16b537SWarner Losh into already allocated destination buffer 'dst', of size 'maxDstSize'. 564*0c16b537SWarner Losh return : size of regenerated data (<= maxDstSize) 565*0c16b537SWarner Losh or an error code, which can be tested using FSE_isError() 566*0c16b537SWarner Losh 567*0c16b537SWarner Losh ** Important ** : FSE_decompress() doesn't decompress non-compressible nor RLE data !!! 568*0c16b537SWarner Losh Why ? : making this distinction requires a header. 569*0c16b537SWarner Losh Header management is intentionally delegated to the user layer, which can better manage special cases. 570*0c16b537SWarner Losh */ 571*0c16b537SWarner Losh 572*0c16b537SWarner Losh 573*0c16b537SWarner Losh /* ***************************************** 574*0c16b537SWarner Losh * Tool functions 575*0c16b537SWarner Losh ******************************************/ 576*0c16b537SWarner Losh /* Error Management */ 577*0c16b537SWarner Losh static unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ 578*0c16b537SWarner Losh 579*0c16b537SWarner Losh 580*0c16b537SWarner Losh 581*0c16b537SWarner Losh /* ***************************************** 582*0c16b537SWarner Losh * FSE detailed API 583*0c16b537SWarner Losh ******************************************/ 584*0c16b537SWarner Losh /*! 585*0c16b537SWarner Losh FSE_compress() does the following: 586*0c16b537SWarner Losh 1. count symbol occurrence from source[] into table count[] 587*0c16b537SWarner Losh 2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) 588*0c16b537SWarner Losh 3. save normalized counters to memory buffer using writeNCount() 589*0c16b537SWarner Losh 4. build encoding table 'CTable' from normalized counters 590*0c16b537SWarner Losh 5. encode the data stream using encoding table 'CTable' 591*0c16b537SWarner Losh 592*0c16b537SWarner Losh FSE_decompress() does the following: 593*0c16b537SWarner Losh 1. read normalized counters with readNCount() 594*0c16b537SWarner Losh 2. build decoding table 'DTable' from normalized counters 595*0c16b537SWarner Losh 3. decode the data stream using decoding table 'DTable' 596*0c16b537SWarner Losh 597*0c16b537SWarner Losh The following API allows targeting specific sub-functions for advanced tasks. 598*0c16b537SWarner Losh For example, it's possible to compress several blocks using the same 'CTable', 599*0c16b537SWarner Losh or to save and provide normalized distribution using external method. 600*0c16b537SWarner Losh */ 601*0c16b537SWarner Losh 602*0c16b537SWarner Losh 603*0c16b537SWarner Losh /* *** DECOMPRESSION *** */ 604*0c16b537SWarner Losh 605*0c16b537SWarner Losh /*! 606*0c16b537SWarner Losh FSE_readNCount(): 607*0c16b537SWarner Losh Read compactly saved 'normalizedCounter' from 'rBuffer'. 608*0c16b537SWarner Losh return : size read from 'rBuffer' 609*0c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() 610*0c16b537SWarner Losh maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ 611*0c16b537SWarner Losh static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); 612*0c16b537SWarner Losh 613*0c16b537SWarner Losh /*! 614*0c16b537SWarner Losh Constructor and Destructor of type FSE_DTable 615*0c16b537SWarner Losh Note that its size depends on 'tableLog' */ 616*0c16b537SWarner Losh typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ 617*0c16b537SWarner Losh 618*0c16b537SWarner Losh /*! 619*0c16b537SWarner Losh FSE_buildDTable(): 620*0c16b537SWarner Losh Builds 'dt', which must be already allocated, using FSE_createDTable() 621*0c16b537SWarner Losh return : 0, 622*0c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() */ 623*0c16b537SWarner Losh static size_t FSE_buildDTable ( FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); 624*0c16b537SWarner Losh 625*0c16b537SWarner Losh /*! 626*0c16b537SWarner Losh FSE_decompress_usingDTable(): 627*0c16b537SWarner Losh Decompress compressed source 'cSrc' of size 'cSrcSize' using 'dt' 628*0c16b537SWarner Losh into 'dst' which must be already allocated. 629*0c16b537SWarner Losh return : size of regenerated data (necessarily <= maxDstSize) 630*0c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() */ 631*0c16b537SWarner Losh static size_t FSE_decompress_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); 632*0c16b537SWarner Losh 633*0c16b537SWarner Losh /*! 634*0c16b537SWarner Losh Tutorial : 635*0c16b537SWarner Losh ---------- 636*0c16b537SWarner Losh (Note : these functions only decompress FSE-compressed blocks. 637*0c16b537SWarner Losh If block is uncompressed, use memcpy() instead 638*0c16b537SWarner Losh If block is a single repeated byte, use memset() instead ) 639*0c16b537SWarner Losh 640*0c16b537SWarner Losh The first step is to obtain the normalized frequencies of symbols. 641*0c16b537SWarner Losh This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount(). 642*0c16b537SWarner Losh 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short. 643*0c16b537SWarner Losh In practice, that means it's necessary to know 'maxSymbolValue' beforehand, 644*0c16b537SWarner Losh or size the table to handle worst case situations (typically 256). 645*0c16b537SWarner Losh FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'. 646*0c16b537SWarner Losh The result of FSE_readNCount() is the number of bytes read from 'rBuffer'. 647*0c16b537SWarner Losh Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that. 648*0c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError(). 649*0c16b537SWarner Losh 650*0c16b537SWarner Losh The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'. 651*0c16b537SWarner Losh This is performed by the function FSE_buildDTable(). 652*0c16b537SWarner Losh The space required by 'FSE_DTable' must be already allocated using FSE_createDTable(). 653*0c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError(). 654*0c16b537SWarner Losh 655*0c16b537SWarner Losh 'FSE_DTable' can then be used to decompress 'cSrc', with FSE_decompress_usingDTable(). 656*0c16b537SWarner Losh 'cSrcSize' must be strictly correct, otherwise decompression will fail. 657*0c16b537SWarner Losh FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=maxDstSize). 658*0c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) 659*0c16b537SWarner Losh */ 660*0c16b537SWarner Losh 661*0c16b537SWarner Losh 662*0c16b537SWarner Losh #if defined (__cplusplus) 663*0c16b537SWarner Losh } 664*0c16b537SWarner Losh #endif 665*0c16b537SWarner Losh 666*0c16b537SWarner Losh #endif /* FSE_H */ 667*0c16b537SWarner Losh 668*0c16b537SWarner Losh 669*0c16b537SWarner Losh /* ****************************************************************** 670*0c16b537SWarner Losh bitstream 671*0c16b537SWarner Losh Part of NewGen Entropy library 672*0c16b537SWarner Losh header file (to include) 673*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 674*0c16b537SWarner Losh 675*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 676*0c16b537SWarner Losh 677*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 678*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 679*0c16b537SWarner Losh met: 680*0c16b537SWarner Losh 681*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 682*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 683*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 684*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 685*0c16b537SWarner Losh in the documentation and/or other materials provided with the 686*0c16b537SWarner Losh distribution. 687*0c16b537SWarner Losh 688*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 689*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 690*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 691*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 692*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 693*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 694*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 695*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 696*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 697*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 698*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 699*0c16b537SWarner Losh 700*0c16b537SWarner Losh You can contact the author at : 701*0c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 702*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 703*0c16b537SWarner Losh ****************************************************************** */ 704*0c16b537SWarner Losh #ifndef BITSTREAM_H_MODULE 705*0c16b537SWarner Losh #define BITSTREAM_H_MODULE 706*0c16b537SWarner Losh 707*0c16b537SWarner Losh #if defined (__cplusplus) 708*0c16b537SWarner Losh extern "C" { 709*0c16b537SWarner Losh #endif 710*0c16b537SWarner Losh 711*0c16b537SWarner Losh 712*0c16b537SWarner Losh /* 713*0c16b537SWarner Losh * This API consists of small unitary functions, which highly benefit from being inlined. 714*0c16b537SWarner Losh * Since link-time-optimization is not available for all compilers, 715*0c16b537SWarner Losh * these functions are defined into a .h to be included. 716*0c16b537SWarner Losh */ 717*0c16b537SWarner Losh 718*0c16b537SWarner Losh /********************************************** 719*0c16b537SWarner Losh * bitStream decompression API (read backward) 720*0c16b537SWarner Losh **********************************************/ 721*0c16b537SWarner Losh typedef struct 722*0c16b537SWarner Losh { 723*0c16b537SWarner Losh size_t bitContainer; 724*0c16b537SWarner Losh unsigned bitsConsumed; 725*0c16b537SWarner Losh const char* ptr; 726*0c16b537SWarner Losh const char* start; 727*0c16b537SWarner Losh } BIT_DStream_t; 728*0c16b537SWarner Losh 729*0c16b537SWarner Losh typedef enum { BIT_DStream_unfinished = 0, 730*0c16b537SWarner Losh BIT_DStream_endOfBuffer = 1, 731*0c16b537SWarner Losh BIT_DStream_completed = 2, 732*0c16b537SWarner Losh BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ 733*0c16b537SWarner Losh /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ 734*0c16b537SWarner Losh 735*0c16b537SWarner Losh MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); 736*0c16b537SWarner Losh MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); 737*0c16b537SWarner Losh MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); 738*0c16b537SWarner Losh MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); 739*0c16b537SWarner Losh 740*0c16b537SWarner Losh 741*0c16b537SWarner Losh /* 742*0c16b537SWarner Losh * Start by invoking BIT_initDStream(). 743*0c16b537SWarner Losh * A chunk of the bitStream is then stored into a local register. 744*0c16b537SWarner Losh * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). 745*0c16b537SWarner Losh * You can then retrieve bitFields stored into the local register, **in reverse order**. 746*0c16b537SWarner Losh * Local register is manually filled from memory by the BIT_reloadDStream() method. 747*0c16b537SWarner Losh * A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished. 748*0c16b537SWarner Losh * Otherwise, it can be less than that, so proceed accordingly. 749*0c16b537SWarner Losh * Checking if DStream has reached its end can be performed with BIT_endOfDStream() 750*0c16b537SWarner Losh */ 751*0c16b537SWarner Losh 752*0c16b537SWarner Losh 753*0c16b537SWarner Losh /****************************************** 754*0c16b537SWarner Losh * unsafe API 755*0c16b537SWarner Losh ******************************************/ 756*0c16b537SWarner Losh MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); 757*0c16b537SWarner Losh /* faster, but works only if nbBits >= 1 */ 758*0c16b537SWarner Losh 759*0c16b537SWarner Losh 760*0c16b537SWarner Losh 761*0c16b537SWarner Losh /**************************************************************** 762*0c16b537SWarner Losh * Helper functions 763*0c16b537SWarner Losh ****************************************************************/ 764*0c16b537SWarner Losh MEM_STATIC unsigned BIT_highbit32 (register U32 val) 765*0c16b537SWarner Losh { 766*0c16b537SWarner Losh # if defined(_MSC_VER) /* Visual */ 767*0c16b537SWarner Losh unsigned long r=0; 768*0c16b537SWarner Losh _BitScanReverse ( &r, val ); 769*0c16b537SWarner Losh return (unsigned) r; 770*0c16b537SWarner Losh # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ 771*0c16b537SWarner Losh return 31 - __builtin_clz (val); 772*0c16b537SWarner Losh # else /* Software version */ 773*0c16b537SWarner Losh static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; 774*0c16b537SWarner Losh U32 v = val; 775*0c16b537SWarner Losh unsigned r; 776*0c16b537SWarner Losh v |= v >> 1; 777*0c16b537SWarner Losh v |= v >> 2; 778*0c16b537SWarner Losh v |= v >> 4; 779*0c16b537SWarner Losh v |= v >> 8; 780*0c16b537SWarner Losh v |= v >> 16; 781*0c16b537SWarner Losh r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; 782*0c16b537SWarner Losh return r; 783*0c16b537SWarner Losh # endif 784*0c16b537SWarner Losh } 785*0c16b537SWarner Losh 786*0c16b537SWarner Losh 787*0c16b537SWarner Losh /********************************************************** 788*0c16b537SWarner Losh * bitStream decoding 789*0c16b537SWarner Losh **********************************************************/ 790*0c16b537SWarner Losh 791*0c16b537SWarner Losh /*!BIT_initDStream 792*0c16b537SWarner Losh * Initialize a BIT_DStream_t. 793*0c16b537SWarner Losh * @bitD : a pointer to an already allocated BIT_DStream_t structure 794*0c16b537SWarner Losh * @srcBuffer must point at the beginning of a bitStream 795*0c16b537SWarner Losh * @srcSize must be the exact size of the bitStream 796*0c16b537SWarner Losh * @result : size of stream (== srcSize) or an errorCode if a problem is detected 797*0c16b537SWarner Losh */ 798*0c16b537SWarner Losh MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) 799*0c16b537SWarner Losh { 800*0c16b537SWarner Losh if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } 801*0c16b537SWarner Losh 802*0c16b537SWarner Losh if (srcSize >= sizeof(size_t)) /* normal case */ 803*0c16b537SWarner Losh { 804*0c16b537SWarner Losh U32 contain32; 805*0c16b537SWarner Losh bitD->start = (const char*)srcBuffer; 806*0c16b537SWarner Losh bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t); 807*0c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr); 808*0c16b537SWarner Losh contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; 809*0c16b537SWarner Losh if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ 810*0c16b537SWarner Losh bitD->bitsConsumed = 8 - BIT_highbit32(contain32); 811*0c16b537SWarner Losh } 812*0c16b537SWarner Losh else 813*0c16b537SWarner Losh { 814*0c16b537SWarner Losh U32 contain32; 815*0c16b537SWarner Losh bitD->start = (const char*)srcBuffer; 816*0c16b537SWarner Losh bitD->ptr = bitD->start; 817*0c16b537SWarner Losh bitD->bitContainer = *(const BYTE*)(bitD->start); 818*0c16b537SWarner Losh switch(srcSize) 819*0c16b537SWarner Losh { 820*0c16b537SWarner Losh case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */ 821*0c16b537SWarner Losh case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */ 822*0c16b537SWarner Losh case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */ 823*0c16b537SWarner Losh case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */ 824*0c16b537SWarner Losh case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */ 825*0c16b537SWarner Losh case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; /* fall-through */ 826*0c16b537SWarner Losh default: break; 827*0c16b537SWarner Losh } 828*0c16b537SWarner Losh contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; 829*0c16b537SWarner Losh if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ 830*0c16b537SWarner Losh bitD->bitsConsumed = 8 - BIT_highbit32(contain32); 831*0c16b537SWarner Losh bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8; 832*0c16b537SWarner Losh } 833*0c16b537SWarner Losh 834*0c16b537SWarner Losh return srcSize; 835*0c16b537SWarner Losh } 836*0c16b537SWarner Losh 837*0c16b537SWarner Losh /*!BIT_lookBits 838*0c16b537SWarner Losh * Provides next n bits from local register 839*0c16b537SWarner Losh * local register is not modified (bits are still present for next read/look) 840*0c16b537SWarner Losh * On 32-bits, maxNbBits==25 841*0c16b537SWarner Losh * On 64-bits, maxNbBits==57 842*0c16b537SWarner Losh * @return : value extracted 843*0c16b537SWarner Losh */ 844*0c16b537SWarner Losh MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits) 845*0c16b537SWarner Losh { 846*0c16b537SWarner Losh const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; 847*0c16b537SWarner Losh return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); 848*0c16b537SWarner Losh } 849*0c16b537SWarner Losh 850*0c16b537SWarner Losh /*! BIT_lookBitsFast : 851*0c16b537SWarner Losh * unsafe version; only works only if nbBits >= 1 */ 852*0c16b537SWarner Losh MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits) 853*0c16b537SWarner Losh { 854*0c16b537SWarner Losh const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; 855*0c16b537SWarner Losh return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask); 856*0c16b537SWarner Losh } 857*0c16b537SWarner Losh 858*0c16b537SWarner Losh MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) 859*0c16b537SWarner Losh { 860*0c16b537SWarner Losh bitD->bitsConsumed += nbBits; 861*0c16b537SWarner Losh } 862*0c16b537SWarner Losh 863*0c16b537SWarner Losh /*!BIT_readBits 864*0c16b537SWarner Losh * Read next n bits from local register. 865*0c16b537SWarner Losh * pay attention to not read more than nbBits contained into local register. 866*0c16b537SWarner Losh * @return : extracted value. 867*0c16b537SWarner Losh */ 868*0c16b537SWarner Losh MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) 869*0c16b537SWarner Losh { 870*0c16b537SWarner Losh size_t value = BIT_lookBits(bitD, nbBits); 871*0c16b537SWarner Losh BIT_skipBits(bitD, nbBits); 872*0c16b537SWarner Losh return value; 873*0c16b537SWarner Losh } 874*0c16b537SWarner Losh 875*0c16b537SWarner Losh /*!BIT_readBitsFast : 876*0c16b537SWarner Losh * unsafe version; only works only if nbBits >= 1 */ 877*0c16b537SWarner Losh MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) 878*0c16b537SWarner Losh { 879*0c16b537SWarner Losh size_t value = BIT_lookBitsFast(bitD, nbBits); 880*0c16b537SWarner Losh BIT_skipBits(bitD, nbBits); 881*0c16b537SWarner Losh return value; 882*0c16b537SWarner Losh } 883*0c16b537SWarner Losh 884*0c16b537SWarner Losh MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) 885*0c16b537SWarner Losh { 886*0c16b537SWarner Losh if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */ 887*0c16b537SWarner Losh return BIT_DStream_overflow; 888*0c16b537SWarner Losh 889*0c16b537SWarner Losh if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) 890*0c16b537SWarner Losh { 891*0c16b537SWarner Losh bitD->ptr -= bitD->bitsConsumed >> 3; 892*0c16b537SWarner Losh bitD->bitsConsumed &= 7; 893*0c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr); 894*0c16b537SWarner Losh return BIT_DStream_unfinished; 895*0c16b537SWarner Losh } 896*0c16b537SWarner Losh if (bitD->ptr == bitD->start) 897*0c16b537SWarner Losh { 898*0c16b537SWarner Losh if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; 899*0c16b537SWarner Losh return BIT_DStream_completed; 900*0c16b537SWarner Losh } 901*0c16b537SWarner Losh { 902*0c16b537SWarner Losh U32 nbBytes = bitD->bitsConsumed >> 3; 903*0c16b537SWarner Losh BIT_DStream_status result = BIT_DStream_unfinished; 904*0c16b537SWarner Losh if (bitD->ptr - nbBytes < bitD->start) 905*0c16b537SWarner Losh { 906*0c16b537SWarner Losh nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ 907*0c16b537SWarner Losh result = BIT_DStream_endOfBuffer; 908*0c16b537SWarner Losh } 909*0c16b537SWarner Losh bitD->ptr -= nbBytes; 910*0c16b537SWarner Losh bitD->bitsConsumed -= nbBytes*8; 911*0c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ 912*0c16b537SWarner Losh return result; 913*0c16b537SWarner Losh } 914*0c16b537SWarner Losh } 915*0c16b537SWarner Losh 916*0c16b537SWarner Losh /*! BIT_endOfDStream 917*0c16b537SWarner Losh * @return Tells if DStream has reached its exact end 918*0c16b537SWarner Losh */ 919*0c16b537SWarner Losh MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) 920*0c16b537SWarner Losh { 921*0c16b537SWarner Losh return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); 922*0c16b537SWarner Losh } 923*0c16b537SWarner Losh 924*0c16b537SWarner Losh #if defined (__cplusplus) 925*0c16b537SWarner Losh } 926*0c16b537SWarner Losh #endif 927*0c16b537SWarner Losh 928*0c16b537SWarner Losh #endif /* BITSTREAM_H_MODULE */ 929*0c16b537SWarner Losh 930*0c16b537SWarner Losh 931*0c16b537SWarner Losh 932*0c16b537SWarner Losh /* ****************************************************************** 933*0c16b537SWarner Losh FSE : Finite State Entropy coder 934*0c16b537SWarner Losh header file for static linking (only) 935*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet 936*0c16b537SWarner Losh 937*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 938*0c16b537SWarner Losh 939*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 940*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 941*0c16b537SWarner Losh met: 942*0c16b537SWarner Losh 943*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 944*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 945*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 946*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 947*0c16b537SWarner Losh in the documentation and/or other materials provided with the 948*0c16b537SWarner Losh distribution. 949*0c16b537SWarner Losh 950*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 951*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 952*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 953*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 954*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 955*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 956*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 957*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 958*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 959*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 960*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 961*0c16b537SWarner Losh 962*0c16b537SWarner Losh You can contact the author at : 963*0c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 964*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 965*0c16b537SWarner Losh ****************************************************************** */ 966*0c16b537SWarner Losh #ifndef FSE_STATIC_H 967*0c16b537SWarner Losh #define FSE_STATIC_H 968*0c16b537SWarner Losh 969*0c16b537SWarner Losh #if defined (__cplusplus) 970*0c16b537SWarner Losh extern "C" { 971*0c16b537SWarner Losh #endif 972*0c16b537SWarner Losh 973*0c16b537SWarner Losh 974*0c16b537SWarner Losh /* ***************************************** 975*0c16b537SWarner Losh * Static allocation 976*0c16b537SWarner Losh *******************************************/ 977*0c16b537SWarner Losh /* FSE buffer bounds */ 978*0c16b537SWarner Losh #define FSE_NCOUNTBOUND 512 979*0c16b537SWarner Losh #define FSE_BLOCKBOUND(size) (size + (size>>7)) 980*0c16b537SWarner Losh #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ 981*0c16b537SWarner Losh 982*0c16b537SWarner Losh /* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */ 983*0c16b537SWarner Losh #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) 984*0c16b537SWarner Losh #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) 985*0c16b537SWarner Losh 986*0c16b537SWarner Losh 987*0c16b537SWarner Losh /* ***************************************** 988*0c16b537SWarner Losh * FSE advanced API 989*0c16b537SWarner Losh *******************************************/ 990*0c16b537SWarner Losh static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); 991*0c16b537SWarner Losh /* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */ 992*0c16b537SWarner Losh 993*0c16b537SWarner Losh static size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); 994*0c16b537SWarner Losh /* build a fake FSE_DTable, designed to always generate the same symbolValue */ 995*0c16b537SWarner Losh 996*0c16b537SWarner Losh 997*0c16b537SWarner Losh 998*0c16b537SWarner Losh /* ***************************************** 999*0c16b537SWarner Losh * FSE symbol decompression API 1000*0c16b537SWarner Losh *******************************************/ 1001*0c16b537SWarner Losh typedef struct 1002*0c16b537SWarner Losh { 1003*0c16b537SWarner Losh size_t state; 1004*0c16b537SWarner Losh const void* table; /* precise table may vary, depending on U16 */ 1005*0c16b537SWarner Losh } FSE_DState_t; 1006*0c16b537SWarner Losh 1007*0c16b537SWarner Losh 1008*0c16b537SWarner Losh static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); 1009*0c16b537SWarner Losh 1010*0c16b537SWarner Losh static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); 1011*0c16b537SWarner Losh 1012*0c16b537SWarner Losh static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); 1013*0c16b537SWarner Losh 1014*0c16b537SWarner Losh /*! 1015*0c16b537SWarner Losh Let's now decompose FSE_decompress_usingDTable() into its unitary components. 1016*0c16b537SWarner Losh You will decode FSE-encoded symbols from the bitStream, 1017*0c16b537SWarner Losh and also any other bitFields you put in, **in reverse order**. 1018*0c16b537SWarner Losh 1019*0c16b537SWarner Losh You will need a few variables to track your bitStream. They are : 1020*0c16b537SWarner Losh 1021*0c16b537SWarner Losh BIT_DStream_t DStream; // Stream context 1022*0c16b537SWarner Losh FSE_DState_t DState; // State context. Multiple ones are possible 1023*0c16b537SWarner Losh FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() 1024*0c16b537SWarner Losh 1025*0c16b537SWarner Losh The first thing to do is to init the bitStream. 1026*0c16b537SWarner Losh errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); 1027*0c16b537SWarner Losh 1028*0c16b537SWarner Losh You should then retrieve your initial state(s) 1029*0c16b537SWarner Losh (in reverse flushing order if you have several ones) : 1030*0c16b537SWarner Losh errorCode = FSE_initDState(&DState, &DStream, DTablePtr); 1031*0c16b537SWarner Losh 1032*0c16b537SWarner Losh You can then decode your data, symbol after symbol. 1033*0c16b537SWarner Losh For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. 1034*0c16b537SWarner Losh Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). 1035*0c16b537SWarner Losh unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); 1036*0c16b537SWarner Losh 1037*0c16b537SWarner Losh You can retrieve any bitfield you eventually stored into the bitStream (in reverse order) 1038*0c16b537SWarner Losh Note : maximum allowed nbBits is 25, for 32-bits compatibility 1039*0c16b537SWarner Losh size_t bitField = BIT_readBits(&DStream, nbBits); 1040*0c16b537SWarner Losh 1041*0c16b537SWarner Losh All above operations only read from local register (which size depends on size_t). 1042*0c16b537SWarner Losh Refueling the register from memory is manually performed by the reload method. 1043*0c16b537SWarner Losh endSignal = FSE_reloadDStream(&DStream); 1044*0c16b537SWarner Losh 1045*0c16b537SWarner Losh BIT_reloadDStream() result tells if there is still some more data to read from DStream. 1046*0c16b537SWarner Losh BIT_DStream_unfinished : there is still some data left into the DStream. 1047*0c16b537SWarner Losh BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. 1048*0c16b537SWarner Losh BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. 1049*0c16b537SWarner Losh BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. 1050*0c16b537SWarner Losh 1051*0c16b537SWarner Losh When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, 1052*0c16b537SWarner Losh to properly detect the exact end of stream. 1053*0c16b537SWarner Losh After each decoded symbol, check if DStream is fully consumed using this simple test : 1054*0c16b537SWarner Losh BIT_reloadDStream(&DStream) >= BIT_DStream_completed 1055*0c16b537SWarner Losh 1056*0c16b537SWarner Losh When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. 1057*0c16b537SWarner Losh Checking if DStream has reached its end is performed by : 1058*0c16b537SWarner Losh BIT_endOfDStream(&DStream); 1059*0c16b537SWarner Losh Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. 1060*0c16b537SWarner Losh FSE_endOfDState(&DState); 1061*0c16b537SWarner Losh */ 1062*0c16b537SWarner Losh 1063*0c16b537SWarner Losh 1064*0c16b537SWarner Losh /* ***************************************** 1065*0c16b537SWarner Losh * FSE unsafe API 1066*0c16b537SWarner Losh *******************************************/ 1067*0c16b537SWarner Losh static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); 1068*0c16b537SWarner Losh /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ 1069*0c16b537SWarner Losh 1070*0c16b537SWarner Losh 1071*0c16b537SWarner Losh /* ***************************************** 1072*0c16b537SWarner Losh * Implementation of inlined functions 1073*0c16b537SWarner Losh *******************************************/ 1074*0c16b537SWarner Losh /* decompression */ 1075*0c16b537SWarner Losh 1076*0c16b537SWarner Losh typedef struct { 1077*0c16b537SWarner Losh U16 tableLog; 1078*0c16b537SWarner Losh U16 fastMode; 1079*0c16b537SWarner Losh } FSE_DTableHeader; /* sizeof U32 */ 1080*0c16b537SWarner Losh 1081*0c16b537SWarner Losh typedef struct 1082*0c16b537SWarner Losh { 1083*0c16b537SWarner Losh unsigned short newState; 1084*0c16b537SWarner Losh unsigned char symbol; 1085*0c16b537SWarner Losh unsigned char nbBits; 1086*0c16b537SWarner Losh } FSE_decode_t; /* size == U32 */ 1087*0c16b537SWarner Losh 1088*0c16b537SWarner Losh MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) 1089*0c16b537SWarner Losh { 1090*0c16b537SWarner Losh FSE_DTableHeader DTableH; 1091*0c16b537SWarner Losh memcpy(&DTableH, dt, sizeof(DTableH)); 1092*0c16b537SWarner Losh DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog); 1093*0c16b537SWarner Losh BIT_reloadDStream(bitD); 1094*0c16b537SWarner Losh DStatePtr->table = dt + 1; 1095*0c16b537SWarner Losh } 1096*0c16b537SWarner Losh 1097*0c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) 1098*0c16b537SWarner Losh { 1099*0c16b537SWarner Losh const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 1100*0c16b537SWarner Losh const U32 nbBits = DInfo.nbBits; 1101*0c16b537SWarner Losh BYTE symbol = DInfo.symbol; 1102*0c16b537SWarner Losh size_t lowBits = BIT_readBits(bitD, nbBits); 1103*0c16b537SWarner Losh 1104*0c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits; 1105*0c16b537SWarner Losh return symbol; 1106*0c16b537SWarner Losh } 1107*0c16b537SWarner Losh 1108*0c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) 1109*0c16b537SWarner Losh { 1110*0c16b537SWarner Losh const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 1111*0c16b537SWarner Losh const U32 nbBits = DInfo.nbBits; 1112*0c16b537SWarner Losh BYTE symbol = DInfo.symbol; 1113*0c16b537SWarner Losh size_t lowBits = BIT_readBitsFast(bitD, nbBits); 1114*0c16b537SWarner Losh 1115*0c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits; 1116*0c16b537SWarner Losh return symbol; 1117*0c16b537SWarner Losh } 1118*0c16b537SWarner Losh 1119*0c16b537SWarner Losh MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) 1120*0c16b537SWarner Losh { 1121*0c16b537SWarner Losh return DStatePtr->state == 0; 1122*0c16b537SWarner Losh } 1123*0c16b537SWarner Losh 1124*0c16b537SWarner Losh 1125*0c16b537SWarner Losh #if defined (__cplusplus) 1126*0c16b537SWarner Losh } 1127*0c16b537SWarner Losh #endif 1128*0c16b537SWarner Losh 1129*0c16b537SWarner Losh #endif /* FSE_STATIC_H */ 1130*0c16b537SWarner Losh 1131*0c16b537SWarner Losh /* ****************************************************************** 1132*0c16b537SWarner Losh FSE : Finite State Entropy coder 1133*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 1134*0c16b537SWarner Losh 1135*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 1136*0c16b537SWarner Losh 1137*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 1138*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 1139*0c16b537SWarner Losh met: 1140*0c16b537SWarner Losh 1141*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 1142*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 1143*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 1144*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 1145*0c16b537SWarner Losh in the documentation and/or other materials provided with the 1146*0c16b537SWarner Losh distribution. 1147*0c16b537SWarner Losh 1148*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1149*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1150*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1151*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1152*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1153*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1154*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1155*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1156*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1157*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1158*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1159*0c16b537SWarner Losh 1160*0c16b537SWarner Losh You can contact the author at : 1161*0c16b537SWarner Losh - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy 1162*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 1163*0c16b537SWarner Losh ****************************************************************** */ 1164*0c16b537SWarner Losh 1165*0c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY 1166*0c16b537SWarner Losh 1167*0c16b537SWarner Losh /* ************************************************************** 1168*0c16b537SWarner Losh * Tuning parameters 1169*0c16b537SWarner Losh ****************************************************************/ 1170*0c16b537SWarner Losh /*!MEMORY_USAGE : 1171*0c16b537SWarner Losh * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) 1172*0c16b537SWarner Losh * Increasing memory usage improves compression ratio 1173*0c16b537SWarner Losh * Reduced memory usage can improve speed, due to cache effect 1174*0c16b537SWarner Losh * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ 1175*0c16b537SWarner Losh #define FSE_MAX_MEMORY_USAGE 14 1176*0c16b537SWarner Losh #define FSE_DEFAULT_MEMORY_USAGE 13 1177*0c16b537SWarner Losh 1178*0c16b537SWarner Losh /*!FSE_MAX_SYMBOL_VALUE : 1179*0c16b537SWarner Losh * Maximum symbol value authorized. 1180*0c16b537SWarner Losh * Required for proper stack allocation */ 1181*0c16b537SWarner Losh #define FSE_MAX_SYMBOL_VALUE 255 1182*0c16b537SWarner Losh 1183*0c16b537SWarner Losh 1184*0c16b537SWarner Losh /* ************************************************************** 1185*0c16b537SWarner Losh * template functions type & suffix 1186*0c16b537SWarner Losh ****************************************************************/ 1187*0c16b537SWarner Losh #define FSE_FUNCTION_TYPE BYTE 1188*0c16b537SWarner Losh #define FSE_FUNCTION_EXTENSION 1189*0c16b537SWarner Losh #define FSE_DECODE_TYPE FSE_decode_t 1190*0c16b537SWarner Losh 1191*0c16b537SWarner Losh 1192*0c16b537SWarner Losh #endif /* !FSE_COMMONDEFS_ONLY */ 1193*0c16b537SWarner Losh 1194*0c16b537SWarner Losh /* ************************************************************** 1195*0c16b537SWarner Losh * Compiler specifics 1196*0c16b537SWarner Losh ****************************************************************/ 1197*0c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */ 1198*0c16b537SWarner Losh # define FORCE_INLINE static __forceinline 1199*0c16b537SWarner Losh # include <intrin.h> /* For Visual 2005 */ 1200*0c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 1201*0c16b537SWarner Losh # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ 1202*0c16b537SWarner Losh #else 1203*0c16b537SWarner Losh # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ 1204*0c16b537SWarner Losh # ifdef __GNUC__ 1205*0c16b537SWarner Losh # define FORCE_INLINE static inline __attribute__((always_inline)) 1206*0c16b537SWarner Losh # else 1207*0c16b537SWarner Losh # define FORCE_INLINE static inline 1208*0c16b537SWarner Losh # endif 1209*0c16b537SWarner Losh # else 1210*0c16b537SWarner Losh # define FORCE_INLINE static 1211*0c16b537SWarner Losh # endif /* __STDC_VERSION__ */ 1212*0c16b537SWarner Losh #endif 1213*0c16b537SWarner Losh 1214*0c16b537SWarner Losh 1215*0c16b537SWarner Losh /* ************************************************************** 1216*0c16b537SWarner Losh * Dependencies 1217*0c16b537SWarner Losh ****************************************************************/ 1218*0c16b537SWarner Losh #include <stdlib.h> /* malloc, free, qsort */ 1219*0c16b537SWarner Losh #include <string.h> /* memcpy, memset */ 1220*0c16b537SWarner Losh #include <stdio.h> /* printf (debug) */ 1221*0c16b537SWarner Losh 1222*0c16b537SWarner Losh 1223*0c16b537SWarner Losh /* *************************************************************** 1224*0c16b537SWarner Losh * Constants 1225*0c16b537SWarner Losh *****************************************************************/ 1226*0c16b537SWarner Losh #define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) 1227*0c16b537SWarner Losh #define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG) 1228*0c16b537SWarner Losh #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1) 1229*0c16b537SWarner Losh #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2) 1230*0c16b537SWarner Losh #define FSE_MIN_TABLELOG 5 1231*0c16b537SWarner Losh 1232*0c16b537SWarner Losh #define FSE_TABLELOG_ABSOLUTE_MAX 15 1233*0c16b537SWarner Losh #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX 1234*0c16b537SWarner Losh #error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" 1235*0c16b537SWarner Losh #endif 1236*0c16b537SWarner Losh 1237*0c16b537SWarner Losh 1238*0c16b537SWarner Losh /* ************************************************************** 1239*0c16b537SWarner Losh * Error Management 1240*0c16b537SWarner Losh ****************************************************************/ 1241*0c16b537SWarner Losh #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ 1242*0c16b537SWarner Losh 1243*0c16b537SWarner Losh 1244*0c16b537SWarner Losh /* ************************************************************** 1245*0c16b537SWarner Losh * Complex types 1246*0c16b537SWarner Losh ****************************************************************/ 1247*0c16b537SWarner Losh typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; 1248*0c16b537SWarner Losh 1249*0c16b537SWarner Losh 1250*0c16b537SWarner Losh /*-************************************************************** 1251*0c16b537SWarner Losh * Templates 1252*0c16b537SWarner Losh ****************************************************************/ 1253*0c16b537SWarner Losh /* 1254*0c16b537SWarner Losh designed to be included 1255*0c16b537SWarner Losh for type-specific functions (template emulation in C) 1256*0c16b537SWarner Losh Objective is to write these functions only once, for improved maintenance 1257*0c16b537SWarner Losh */ 1258*0c16b537SWarner Losh 1259*0c16b537SWarner Losh /* safety checks */ 1260*0c16b537SWarner Losh #ifndef FSE_FUNCTION_EXTENSION 1261*0c16b537SWarner Losh # error "FSE_FUNCTION_EXTENSION must be defined" 1262*0c16b537SWarner Losh #endif 1263*0c16b537SWarner Losh #ifndef FSE_FUNCTION_TYPE 1264*0c16b537SWarner Losh # error "FSE_FUNCTION_TYPE must be defined" 1265*0c16b537SWarner Losh #endif 1266*0c16b537SWarner Losh 1267*0c16b537SWarner Losh /* Function names */ 1268*0c16b537SWarner Losh #define FSE_CAT(X,Y) X##Y 1269*0c16b537SWarner Losh #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) 1270*0c16b537SWarner Losh #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) 1271*0c16b537SWarner Losh 1272*0c16b537SWarner Losh static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } 1273*0c16b537SWarner Losh 1274*0c16b537SWarner Losh 1275*0c16b537SWarner Losh static size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) 1276*0c16b537SWarner Losh { 1277*0c16b537SWarner Losh FSE_DTableHeader DTableH; 1278*0c16b537SWarner Losh void* const tdPtr = dt+1; /* because dt is unsigned, 32-bits aligned on 32-bits */ 1279*0c16b537SWarner Losh FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); 1280*0c16b537SWarner Losh const U32 tableSize = 1 << tableLog; 1281*0c16b537SWarner Losh const U32 tableMask = tableSize-1; 1282*0c16b537SWarner Losh const U32 step = FSE_tableStep(tableSize); 1283*0c16b537SWarner Losh U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; 1284*0c16b537SWarner Losh U32 position = 0; 1285*0c16b537SWarner Losh U32 highThreshold = tableSize-1; 1286*0c16b537SWarner Losh const S16 largeLimit= (S16)(1 << (tableLog-1)); 1287*0c16b537SWarner Losh U32 noLarge = 1; 1288*0c16b537SWarner Losh U32 s; 1289*0c16b537SWarner Losh 1290*0c16b537SWarner Losh /* Sanity Checks */ 1291*0c16b537SWarner Losh if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); 1292*0c16b537SWarner Losh if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); 1293*0c16b537SWarner Losh 1294*0c16b537SWarner Losh /* Init, lay down lowprob symbols */ 1295*0c16b537SWarner Losh DTableH.tableLog = (U16)tableLog; 1296*0c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) 1297*0c16b537SWarner Losh { 1298*0c16b537SWarner Losh if (normalizedCounter[s]==-1) 1299*0c16b537SWarner Losh { 1300*0c16b537SWarner Losh tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; 1301*0c16b537SWarner Losh symbolNext[s] = 1; 1302*0c16b537SWarner Losh } 1303*0c16b537SWarner Losh else 1304*0c16b537SWarner Losh { 1305*0c16b537SWarner Losh if (normalizedCounter[s] >= largeLimit) noLarge=0; 1306*0c16b537SWarner Losh symbolNext[s] = normalizedCounter[s]; 1307*0c16b537SWarner Losh } 1308*0c16b537SWarner Losh } 1309*0c16b537SWarner Losh 1310*0c16b537SWarner Losh /* Spread symbols */ 1311*0c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) 1312*0c16b537SWarner Losh { 1313*0c16b537SWarner Losh int i; 1314*0c16b537SWarner Losh for (i=0; i<normalizedCounter[s]; i++) 1315*0c16b537SWarner Losh { 1316*0c16b537SWarner Losh tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; 1317*0c16b537SWarner Losh position = (position + step) & tableMask; 1318*0c16b537SWarner Losh while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ 1319*0c16b537SWarner Losh } 1320*0c16b537SWarner Losh } 1321*0c16b537SWarner Losh 1322*0c16b537SWarner Losh if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ 1323*0c16b537SWarner Losh 1324*0c16b537SWarner Losh /* Build Decoding table */ 1325*0c16b537SWarner Losh { 1326*0c16b537SWarner Losh U32 i; 1327*0c16b537SWarner Losh for (i=0; i<tableSize; i++) 1328*0c16b537SWarner Losh { 1329*0c16b537SWarner Losh FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol); 1330*0c16b537SWarner Losh U16 nextState = symbolNext[symbol]++; 1331*0c16b537SWarner Losh tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) ); 1332*0c16b537SWarner Losh tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize); 1333*0c16b537SWarner Losh } 1334*0c16b537SWarner Losh } 1335*0c16b537SWarner Losh 1336*0c16b537SWarner Losh DTableH.fastMode = (U16)noLarge; 1337*0c16b537SWarner Losh memcpy(dt, &DTableH, sizeof(DTableH)); 1338*0c16b537SWarner Losh return 0; 1339*0c16b537SWarner Losh } 1340*0c16b537SWarner Losh 1341*0c16b537SWarner Losh 1342*0c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY 1343*0c16b537SWarner Losh /****************************************** 1344*0c16b537SWarner Losh * FSE helper functions 1345*0c16b537SWarner Losh ******************************************/ 1346*0c16b537SWarner Losh static unsigned FSE_isError(size_t code) { return ERR_isError(code); } 1347*0c16b537SWarner Losh 1348*0c16b537SWarner Losh 1349*0c16b537SWarner Losh /**************************************************************** 1350*0c16b537SWarner Losh * FSE NCount encoding-decoding 1351*0c16b537SWarner Losh ****************************************************************/ 1352*0c16b537SWarner Losh static short FSE_abs(short a) 1353*0c16b537SWarner Losh { 1354*0c16b537SWarner Losh return a<0 ? -a : a; 1355*0c16b537SWarner Losh } 1356*0c16b537SWarner Losh 1357*0c16b537SWarner Losh static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 1358*0c16b537SWarner Losh const void* headerBuffer, size_t hbSize) 1359*0c16b537SWarner Losh { 1360*0c16b537SWarner Losh const BYTE* const istart = (const BYTE*) headerBuffer; 1361*0c16b537SWarner Losh const BYTE* const iend = istart + hbSize; 1362*0c16b537SWarner Losh const BYTE* ip = istart; 1363*0c16b537SWarner Losh int nbBits; 1364*0c16b537SWarner Losh int remaining; 1365*0c16b537SWarner Losh int threshold; 1366*0c16b537SWarner Losh U32 bitStream; 1367*0c16b537SWarner Losh int bitCount; 1368*0c16b537SWarner Losh unsigned charnum = 0; 1369*0c16b537SWarner Losh int previous0 = 0; 1370*0c16b537SWarner Losh 1371*0c16b537SWarner Losh if (hbSize < 4) return ERROR(srcSize_wrong); 1372*0c16b537SWarner Losh bitStream = MEM_readLE32(ip); 1373*0c16b537SWarner Losh nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ 1374*0c16b537SWarner Losh if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); 1375*0c16b537SWarner Losh bitStream >>= 4; 1376*0c16b537SWarner Losh bitCount = 4; 1377*0c16b537SWarner Losh *tableLogPtr = nbBits; 1378*0c16b537SWarner Losh remaining = (1<<nbBits)+1; 1379*0c16b537SWarner Losh threshold = 1<<nbBits; 1380*0c16b537SWarner Losh nbBits++; 1381*0c16b537SWarner Losh 1382*0c16b537SWarner Losh while ((remaining>1) && (charnum<=*maxSVPtr)) 1383*0c16b537SWarner Losh { 1384*0c16b537SWarner Losh if (previous0) 1385*0c16b537SWarner Losh { 1386*0c16b537SWarner Losh unsigned n0 = charnum; 1387*0c16b537SWarner Losh while ((bitStream & 0xFFFF) == 0xFFFF) 1388*0c16b537SWarner Losh { 1389*0c16b537SWarner Losh n0+=24; 1390*0c16b537SWarner Losh if (ip < iend-5) 1391*0c16b537SWarner Losh { 1392*0c16b537SWarner Losh ip+=2; 1393*0c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> bitCount; 1394*0c16b537SWarner Losh } 1395*0c16b537SWarner Losh else 1396*0c16b537SWarner Losh { 1397*0c16b537SWarner Losh bitStream >>= 16; 1398*0c16b537SWarner Losh bitCount+=16; 1399*0c16b537SWarner Losh } 1400*0c16b537SWarner Losh } 1401*0c16b537SWarner Losh while ((bitStream & 3) == 3) 1402*0c16b537SWarner Losh { 1403*0c16b537SWarner Losh n0+=3; 1404*0c16b537SWarner Losh bitStream>>=2; 1405*0c16b537SWarner Losh bitCount+=2; 1406*0c16b537SWarner Losh } 1407*0c16b537SWarner Losh n0 += bitStream & 3; 1408*0c16b537SWarner Losh bitCount += 2; 1409*0c16b537SWarner Losh if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); 1410*0c16b537SWarner Losh while (charnum < n0) normalizedCounter[charnum++] = 0; 1411*0c16b537SWarner Losh if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) 1412*0c16b537SWarner Losh { 1413*0c16b537SWarner Losh ip += bitCount>>3; 1414*0c16b537SWarner Losh bitCount &= 7; 1415*0c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> bitCount; 1416*0c16b537SWarner Losh } 1417*0c16b537SWarner Losh else 1418*0c16b537SWarner Losh bitStream >>= 2; 1419*0c16b537SWarner Losh } 1420*0c16b537SWarner Losh { 1421*0c16b537SWarner Losh const short max = (short)((2*threshold-1)-remaining); 1422*0c16b537SWarner Losh short count; 1423*0c16b537SWarner Losh 1424*0c16b537SWarner Losh if ((bitStream & (threshold-1)) < (U32)max) 1425*0c16b537SWarner Losh { 1426*0c16b537SWarner Losh count = (short)(bitStream & (threshold-1)); 1427*0c16b537SWarner Losh bitCount += nbBits-1; 1428*0c16b537SWarner Losh } 1429*0c16b537SWarner Losh else 1430*0c16b537SWarner Losh { 1431*0c16b537SWarner Losh count = (short)(bitStream & (2*threshold-1)); 1432*0c16b537SWarner Losh if (count >= threshold) count -= max; 1433*0c16b537SWarner Losh bitCount += nbBits; 1434*0c16b537SWarner Losh } 1435*0c16b537SWarner Losh 1436*0c16b537SWarner Losh count--; /* extra accuracy */ 1437*0c16b537SWarner Losh remaining -= FSE_abs(count); 1438*0c16b537SWarner Losh normalizedCounter[charnum++] = count; 1439*0c16b537SWarner Losh previous0 = !count; 1440*0c16b537SWarner Losh while (remaining < threshold) 1441*0c16b537SWarner Losh { 1442*0c16b537SWarner Losh nbBits--; 1443*0c16b537SWarner Losh threshold >>= 1; 1444*0c16b537SWarner Losh } 1445*0c16b537SWarner Losh 1446*0c16b537SWarner Losh { 1447*0c16b537SWarner Losh if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) 1448*0c16b537SWarner Losh { 1449*0c16b537SWarner Losh ip += bitCount>>3; 1450*0c16b537SWarner Losh bitCount &= 7; 1451*0c16b537SWarner Losh } 1452*0c16b537SWarner Losh else 1453*0c16b537SWarner Losh { 1454*0c16b537SWarner Losh bitCount -= (int)(8 * (iend - 4 - ip)); 1455*0c16b537SWarner Losh ip = iend - 4; 1456*0c16b537SWarner Losh } 1457*0c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> (bitCount & 31); 1458*0c16b537SWarner Losh } 1459*0c16b537SWarner Losh } 1460*0c16b537SWarner Losh } 1461*0c16b537SWarner Losh if (remaining != 1) return ERROR(GENERIC); 1462*0c16b537SWarner Losh *maxSVPtr = charnum-1; 1463*0c16b537SWarner Losh 1464*0c16b537SWarner Losh ip += (bitCount+7)>>3; 1465*0c16b537SWarner Losh if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong); 1466*0c16b537SWarner Losh return ip-istart; 1467*0c16b537SWarner Losh } 1468*0c16b537SWarner Losh 1469*0c16b537SWarner Losh 1470*0c16b537SWarner Losh /********************************************************* 1471*0c16b537SWarner Losh * Decompression (Byte symbols) 1472*0c16b537SWarner Losh *********************************************************/ 1473*0c16b537SWarner Losh static size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) 1474*0c16b537SWarner Losh { 1475*0c16b537SWarner Losh void* ptr = dt; 1476*0c16b537SWarner Losh FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; 1477*0c16b537SWarner Losh void* dPtr = dt + 1; 1478*0c16b537SWarner Losh FSE_decode_t* const cell = (FSE_decode_t*)dPtr; 1479*0c16b537SWarner Losh 1480*0c16b537SWarner Losh DTableH->tableLog = 0; 1481*0c16b537SWarner Losh DTableH->fastMode = 0; 1482*0c16b537SWarner Losh 1483*0c16b537SWarner Losh cell->newState = 0; 1484*0c16b537SWarner Losh cell->symbol = symbolValue; 1485*0c16b537SWarner Losh cell->nbBits = 0; 1486*0c16b537SWarner Losh 1487*0c16b537SWarner Losh return 0; 1488*0c16b537SWarner Losh } 1489*0c16b537SWarner Losh 1490*0c16b537SWarner Losh 1491*0c16b537SWarner Losh static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) 1492*0c16b537SWarner Losh { 1493*0c16b537SWarner Losh void* ptr = dt; 1494*0c16b537SWarner Losh FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; 1495*0c16b537SWarner Losh void* dPtr = dt + 1; 1496*0c16b537SWarner Losh FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr; 1497*0c16b537SWarner Losh const unsigned tableSize = 1 << nbBits; 1498*0c16b537SWarner Losh const unsigned tableMask = tableSize - 1; 1499*0c16b537SWarner Losh const unsigned maxSymbolValue = tableMask; 1500*0c16b537SWarner Losh unsigned s; 1501*0c16b537SWarner Losh 1502*0c16b537SWarner Losh /* Sanity checks */ 1503*0c16b537SWarner Losh if (nbBits < 1) return ERROR(GENERIC); /* min size */ 1504*0c16b537SWarner Losh 1505*0c16b537SWarner Losh /* Build Decoding Table */ 1506*0c16b537SWarner Losh DTableH->tableLog = (U16)nbBits; 1507*0c16b537SWarner Losh DTableH->fastMode = 1; 1508*0c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) 1509*0c16b537SWarner Losh { 1510*0c16b537SWarner Losh dinfo[s].newState = 0; 1511*0c16b537SWarner Losh dinfo[s].symbol = (BYTE)s; 1512*0c16b537SWarner Losh dinfo[s].nbBits = (BYTE)nbBits; 1513*0c16b537SWarner Losh } 1514*0c16b537SWarner Losh 1515*0c16b537SWarner Losh return 0; 1516*0c16b537SWarner Losh } 1517*0c16b537SWarner Losh 1518*0c16b537SWarner Losh FORCE_INLINE size_t FSE_decompress_usingDTable_generic( 1519*0c16b537SWarner Losh void* dst, size_t maxDstSize, 1520*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize, 1521*0c16b537SWarner Losh const FSE_DTable* dt, const unsigned fast) 1522*0c16b537SWarner Losh { 1523*0c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst; 1524*0c16b537SWarner Losh BYTE* op = ostart; 1525*0c16b537SWarner Losh BYTE* const omax = op + maxDstSize; 1526*0c16b537SWarner Losh BYTE* const olimit = omax-3; 1527*0c16b537SWarner Losh 1528*0c16b537SWarner Losh BIT_DStream_t bitD; 1529*0c16b537SWarner Losh FSE_DState_t state1; 1530*0c16b537SWarner Losh FSE_DState_t state2; 1531*0c16b537SWarner Losh size_t errorCode; 1532*0c16b537SWarner Losh 1533*0c16b537SWarner Losh /* Init */ 1534*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ 1535*0c16b537SWarner Losh if (FSE_isError(errorCode)) return errorCode; 1536*0c16b537SWarner Losh 1537*0c16b537SWarner Losh FSE_initDState(&state1, &bitD, dt); 1538*0c16b537SWarner Losh FSE_initDState(&state2, &bitD, dt); 1539*0c16b537SWarner Losh 1540*0c16b537SWarner Losh #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) 1541*0c16b537SWarner Losh 1542*0c16b537SWarner Losh /* 4 symbols per loop */ 1543*0c16b537SWarner Losh for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4) 1544*0c16b537SWarner Losh { 1545*0c16b537SWarner Losh op[0] = FSE_GETSYMBOL(&state1); 1546*0c16b537SWarner Losh 1547*0c16b537SWarner Losh if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ 1548*0c16b537SWarner Losh BIT_reloadDStream(&bitD); 1549*0c16b537SWarner Losh 1550*0c16b537SWarner Losh op[1] = FSE_GETSYMBOL(&state2); 1551*0c16b537SWarner Losh 1552*0c16b537SWarner Losh if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ 1553*0c16b537SWarner Losh { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } 1554*0c16b537SWarner Losh 1555*0c16b537SWarner Losh op[2] = FSE_GETSYMBOL(&state1); 1556*0c16b537SWarner Losh 1557*0c16b537SWarner Losh if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ 1558*0c16b537SWarner Losh BIT_reloadDStream(&bitD); 1559*0c16b537SWarner Losh 1560*0c16b537SWarner Losh op[3] = FSE_GETSYMBOL(&state2); 1561*0c16b537SWarner Losh } 1562*0c16b537SWarner Losh 1563*0c16b537SWarner Losh /* tail */ 1564*0c16b537SWarner Losh /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ 1565*0c16b537SWarner Losh while (1) 1566*0c16b537SWarner Losh { 1567*0c16b537SWarner Losh if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) ) 1568*0c16b537SWarner Losh break; 1569*0c16b537SWarner Losh 1570*0c16b537SWarner Losh *op++ = FSE_GETSYMBOL(&state1); 1571*0c16b537SWarner Losh 1572*0c16b537SWarner Losh if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) ) 1573*0c16b537SWarner Losh break; 1574*0c16b537SWarner Losh 1575*0c16b537SWarner Losh *op++ = FSE_GETSYMBOL(&state2); 1576*0c16b537SWarner Losh } 1577*0c16b537SWarner Losh 1578*0c16b537SWarner Losh /* end ? */ 1579*0c16b537SWarner Losh if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) 1580*0c16b537SWarner Losh return op-ostart; 1581*0c16b537SWarner Losh 1582*0c16b537SWarner Losh if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */ 1583*0c16b537SWarner Losh 1584*0c16b537SWarner Losh return ERROR(corruption_detected); 1585*0c16b537SWarner Losh } 1586*0c16b537SWarner Losh 1587*0c16b537SWarner Losh 1588*0c16b537SWarner Losh static size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, 1589*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize, 1590*0c16b537SWarner Losh const FSE_DTable* dt) 1591*0c16b537SWarner Losh { 1592*0c16b537SWarner Losh FSE_DTableHeader DTableH; 1593*0c16b537SWarner Losh U32 fastMode; 1594*0c16b537SWarner Losh 1595*0c16b537SWarner Losh memcpy(&DTableH, dt, sizeof(DTableH)); 1596*0c16b537SWarner Losh fastMode = DTableH.fastMode; 1597*0c16b537SWarner Losh 1598*0c16b537SWarner Losh /* select fast mode (static) */ 1599*0c16b537SWarner Losh if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); 1600*0c16b537SWarner Losh return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); 1601*0c16b537SWarner Losh } 1602*0c16b537SWarner Losh 1603*0c16b537SWarner Losh 1604*0c16b537SWarner Losh static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize) 1605*0c16b537SWarner Losh { 1606*0c16b537SWarner Losh const BYTE* const istart = (const BYTE*)cSrc; 1607*0c16b537SWarner Losh const BYTE* ip = istart; 1608*0c16b537SWarner Losh short counting[FSE_MAX_SYMBOL_VALUE+1]; 1609*0c16b537SWarner Losh DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ 1610*0c16b537SWarner Losh unsigned tableLog; 1611*0c16b537SWarner Losh unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; 1612*0c16b537SWarner Losh size_t errorCode; 1613*0c16b537SWarner Losh 1614*0c16b537SWarner Losh if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */ 1615*0c16b537SWarner Losh 1616*0c16b537SWarner Losh /* normal FSE decoding mode */ 1617*0c16b537SWarner Losh errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); 1618*0c16b537SWarner Losh if (FSE_isError(errorCode)) return errorCode; 1619*0c16b537SWarner Losh if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */ 1620*0c16b537SWarner Losh ip += errorCode; 1621*0c16b537SWarner Losh cSrcSize -= errorCode; 1622*0c16b537SWarner Losh 1623*0c16b537SWarner Losh errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog); 1624*0c16b537SWarner Losh if (FSE_isError(errorCode)) return errorCode; 1625*0c16b537SWarner Losh 1626*0c16b537SWarner Losh /* always return, even if it is an error code */ 1627*0c16b537SWarner Losh return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); 1628*0c16b537SWarner Losh } 1629*0c16b537SWarner Losh 1630*0c16b537SWarner Losh 1631*0c16b537SWarner Losh 1632*0c16b537SWarner Losh #endif /* FSE_COMMONDEFS_ONLY */ 1633*0c16b537SWarner Losh 1634*0c16b537SWarner Losh 1635*0c16b537SWarner Losh /* ****************************************************************** 1636*0c16b537SWarner Losh Huff0 : Huffman coder, part of New Generation Entropy library 1637*0c16b537SWarner Losh header file 1638*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 1639*0c16b537SWarner Losh 1640*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 1641*0c16b537SWarner Losh 1642*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 1643*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 1644*0c16b537SWarner Losh met: 1645*0c16b537SWarner Losh 1646*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 1647*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 1648*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 1649*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 1650*0c16b537SWarner Losh in the documentation and/or other materials provided with the 1651*0c16b537SWarner Losh distribution. 1652*0c16b537SWarner Losh 1653*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1654*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1655*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1656*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1657*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1658*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1659*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1660*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1661*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1662*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1663*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1664*0c16b537SWarner Losh 1665*0c16b537SWarner Losh You can contact the author at : 1666*0c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 1667*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 1668*0c16b537SWarner Losh ****************************************************************** */ 1669*0c16b537SWarner Losh #ifndef HUFF0_H 1670*0c16b537SWarner Losh #define HUFF0_H 1671*0c16b537SWarner Losh 1672*0c16b537SWarner Losh #if defined (__cplusplus) 1673*0c16b537SWarner Losh extern "C" { 1674*0c16b537SWarner Losh #endif 1675*0c16b537SWarner Losh 1676*0c16b537SWarner Losh 1677*0c16b537SWarner Losh /* **************************************** 1678*0c16b537SWarner Losh * Dependency 1679*0c16b537SWarner Losh ******************************************/ 1680*0c16b537SWarner Losh #include <stddef.h> /* size_t */ 1681*0c16b537SWarner Losh 1682*0c16b537SWarner Losh 1683*0c16b537SWarner Losh /* **************************************** 1684*0c16b537SWarner Losh * Huff0 simple functions 1685*0c16b537SWarner Losh ******************************************/ 1686*0c16b537SWarner Losh static size_t HUF_decompress(void* dst, size_t dstSize, 1687*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize); 1688*0c16b537SWarner Losh /*! 1689*0c16b537SWarner Losh HUF_decompress(): 1690*0c16b537SWarner Losh Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize', 1691*0c16b537SWarner Losh into already allocated destination buffer 'dst', of size 'dstSize'. 1692*0c16b537SWarner Losh 'dstSize' must be the exact size of original (uncompressed) data. 1693*0c16b537SWarner Losh Note : in contrast with FSE, HUF_decompress can regenerate RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, because it knows size to regenerate. 1694*0c16b537SWarner Losh @return : size of regenerated data (== dstSize) 1695*0c16b537SWarner Losh or an error code, which can be tested using HUF_isError() 1696*0c16b537SWarner Losh */ 1697*0c16b537SWarner Losh 1698*0c16b537SWarner Losh 1699*0c16b537SWarner Losh /* **************************************** 1700*0c16b537SWarner Losh * Tool functions 1701*0c16b537SWarner Losh ******************************************/ 1702*0c16b537SWarner Losh /* Error Management */ 1703*0c16b537SWarner Losh static unsigned HUF_isError(size_t code); /* tells if a return value is an error code */ 1704*0c16b537SWarner Losh 1705*0c16b537SWarner Losh 1706*0c16b537SWarner Losh #if defined (__cplusplus) 1707*0c16b537SWarner Losh } 1708*0c16b537SWarner Losh #endif 1709*0c16b537SWarner Losh 1710*0c16b537SWarner Losh #endif /* HUFF0_H */ 1711*0c16b537SWarner Losh 1712*0c16b537SWarner Losh 1713*0c16b537SWarner Losh /* ****************************************************************** 1714*0c16b537SWarner Losh Huff0 : Huffman coder, part of New Generation Entropy library 1715*0c16b537SWarner Losh header file for static linking (only) 1716*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet 1717*0c16b537SWarner Losh 1718*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 1719*0c16b537SWarner Losh 1720*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 1721*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 1722*0c16b537SWarner Losh met: 1723*0c16b537SWarner Losh 1724*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 1725*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 1726*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 1727*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 1728*0c16b537SWarner Losh in the documentation and/or other materials provided with the 1729*0c16b537SWarner Losh distribution. 1730*0c16b537SWarner Losh 1731*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1732*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1733*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1734*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1735*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1736*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1737*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1738*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1739*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1740*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1741*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1742*0c16b537SWarner Losh 1743*0c16b537SWarner Losh You can contact the author at : 1744*0c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 1745*0c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c 1746*0c16b537SWarner Losh ****************************************************************** */ 1747*0c16b537SWarner Losh #ifndef HUFF0_STATIC_H 1748*0c16b537SWarner Losh #define HUFF0_STATIC_H 1749*0c16b537SWarner Losh 1750*0c16b537SWarner Losh #if defined (__cplusplus) 1751*0c16b537SWarner Losh extern "C" { 1752*0c16b537SWarner Losh #endif 1753*0c16b537SWarner Losh 1754*0c16b537SWarner Losh 1755*0c16b537SWarner Losh 1756*0c16b537SWarner Losh /* **************************************** 1757*0c16b537SWarner Losh * Static allocation macros 1758*0c16b537SWarner Losh ******************************************/ 1759*0c16b537SWarner Losh /* static allocation of Huff0's DTable */ 1760*0c16b537SWarner Losh #define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<maxTableLog)) /* nb Cells; use unsigned short for X2, unsigned int for X4 */ 1761*0c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ 1762*0c16b537SWarner Losh unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog } 1763*0c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \ 1764*0c16b537SWarner Losh unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog } 1765*0c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \ 1766*0c16b537SWarner Losh unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog } 1767*0c16b537SWarner Losh 1768*0c16b537SWarner Losh 1769*0c16b537SWarner Losh /* **************************************** 1770*0c16b537SWarner Losh * Advanced decompression functions 1771*0c16b537SWarner Losh ******************************************/ 1772*0c16b537SWarner Losh static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ 1773*0c16b537SWarner Losh static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */ 1774*0c16b537SWarner Losh 1775*0c16b537SWarner Losh 1776*0c16b537SWarner Losh /* **************************************** 1777*0c16b537SWarner Losh * Huff0 detailed API 1778*0c16b537SWarner Losh ******************************************/ 1779*0c16b537SWarner Losh /*! 1780*0c16b537SWarner Losh HUF_decompress() does the following: 1781*0c16b537SWarner Losh 1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics 1782*0c16b537SWarner Losh 2. build Huffman table from save, using HUF_readDTableXn() 1783*0c16b537SWarner Losh 3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable 1784*0c16b537SWarner Losh 1785*0c16b537SWarner Losh */ 1786*0c16b537SWarner Losh static size_t HUF_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); 1787*0c16b537SWarner Losh static size_t HUF_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); 1788*0c16b537SWarner Losh 1789*0c16b537SWarner Losh static size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); 1790*0c16b537SWarner Losh static size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); 1791*0c16b537SWarner Losh 1792*0c16b537SWarner Losh 1793*0c16b537SWarner Losh #if defined (__cplusplus) 1794*0c16b537SWarner Losh } 1795*0c16b537SWarner Losh #endif 1796*0c16b537SWarner Losh 1797*0c16b537SWarner Losh #endif /* HUFF0_STATIC_H */ 1798*0c16b537SWarner Losh 1799*0c16b537SWarner Losh 1800*0c16b537SWarner Losh 1801*0c16b537SWarner Losh /* ****************************************************************** 1802*0c16b537SWarner Losh Huff0 : Huffman coder, part of New Generation Entropy library 1803*0c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet. 1804*0c16b537SWarner Losh 1805*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 1806*0c16b537SWarner Losh 1807*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 1808*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 1809*0c16b537SWarner Losh met: 1810*0c16b537SWarner Losh 1811*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 1812*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 1813*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 1814*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 1815*0c16b537SWarner Losh in the documentation and/or other materials provided with the 1816*0c16b537SWarner Losh distribution. 1817*0c16b537SWarner Losh 1818*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1819*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1820*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1821*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1822*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1823*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1824*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1825*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1826*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1827*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1828*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1829*0c16b537SWarner Losh 1830*0c16b537SWarner Losh You can contact the author at : 1831*0c16b537SWarner Losh - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy 1832*0c16b537SWarner Losh ****************************************************************** */ 1833*0c16b537SWarner Losh 1834*0c16b537SWarner Losh /* ************************************************************** 1835*0c16b537SWarner Losh * Compiler specifics 1836*0c16b537SWarner Losh ****************************************************************/ 1837*0c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 1838*0c16b537SWarner Losh /* inline is defined */ 1839*0c16b537SWarner Losh #elif defined(_MSC_VER) 1840*0c16b537SWarner Losh # define inline __inline 1841*0c16b537SWarner Losh #else 1842*0c16b537SWarner Losh # define inline /* disable inline */ 1843*0c16b537SWarner Losh #endif 1844*0c16b537SWarner Losh 1845*0c16b537SWarner Losh 1846*0c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */ 1847*0c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 1848*0c16b537SWarner Losh #endif 1849*0c16b537SWarner Losh 1850*0c16b537SWarner Losh 1851*0c16b537SWarner Losh /* ************************************************************** 1852*0c16b537SWarner Losh * Includes 1853*0c16b537SWarner Losh ****************************************************************/ 1854*0c16b537SWarner Losh #include <stdlib.h> /* malloc, free, qsort */ 1855*0c16b537SWarner Losh #include <string.h> /* memcpy, memset */ 1856*0c16b537SWarner Losh #include <stdio.h> /* printf (debug) */ 1857*0c16b537SWarner Losh 1858*0c16b537SWarner Losh 1859*0c16b537SWarner Losh /* ************************************************************** 1860*0c16b537SWarner Losh * Constants 1861*0c16b537SWarner Losh ****************************************************************/ 1862*0c16b537SWarner Losh #define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ 1863*0c16b537SWarner Losh #define HUF_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ 1864*0c16b537SWarner Losh #define HUF_DEFAULT_TABLELOG HUF_MAX_TABLELOG /* tableLog by default, when not specified */ 1865*0c16b537SWarner Losh #define HUF_MAX_SYMBOL_VALUE 255 1866*0c16b537SWarner Losh #if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) 1867*0c16b537SWarner Losh # error "HUF_MAX_TABLELOG is too large !" 1868*0c16b537SWarner Losh #endif 1869*0c16b537SWarner Losh 1870*0c16b537SWarner Losh 1871*0c16b537SWarner Losh /* ************************************************************** 1872*0c16b537SWarner Losh * Error Management 1873*0c16b537SWarner Losh ****************************************************************/ 1874*0c16b537SWarner Losh static unsigned HUF_isError(size_t code) { return ERR_isError(code); } 1875*0c16b537SWarner Losh #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ 1876*0c16b537SWarner Losh 1877*0c16b537SWarner Losh 1878*0c16b537SWarner Losh 1879*0c16b537SWarner Losh /*-******************************************************* 1880*0c16b537SWarner Losh * Huff0 : Huffman block decompression 1881*0c16b537SWarner Losh *********************************************************/ 1882*0c16b537SWarner Losh typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2; /* single-symbol decoding */ 1883*0c16b537SWarner Losh 1884*0c16b537SWarner Losh typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */ 1885*0c16b537SWarner Losh 1886*0c16b537SWarner Losh typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t; 1887*0c16b537SWarner Losh 1888*0c16b537SWarner Losh /*! HUF_readStats 1889*0c16b537SWarner Losh Read compact Huffman tree, saved by HUF_writeCTable 1890*0c16b537SWarner Losh @huffWeight : destination buffer 1891*0c16b537SWarner Losh @return : size read from `src` 1892*0c16b537SWarner Losh */ 1893*0c16b537SWarner Losh static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, 1894*0c16b537SWarner Losh U32* nbSymbolsPtr, U32* tableLogPtr, 1895*0c16b537SWarner Losh const void* src, size_t srcSize) 1896*0c16b537SWarner Losh { 1897*0c16b537SWarner Losh U32 weightTotal; 1898*0c16b537SWarner Losh U32 tableLog; 1899*0c16b537SWarner Losh const BYTE* ip = (const BYTE*) src; 1900*0c16b537SWarner Losh size_t iSize; 1901*0c16b537SWarner Losh size_t oSize; 1902*0c16b537SWarner Losh U32 n; 1903*0c16b537SWarner Losh 1904*0c16b537SWarner Losh if (!srcSize) return ERROR(srcSize_wrong); 1905*0c16b537SWarner Losh iSize = ip[0]; 1906*0c16b537SWarner Losh //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ 1907*0c16b537SWarner Losh 1908*0c16b537SWarner Losh if (iSize >= 128) /* special header */ 1909*0c16b537SWarner Losh { 1910*0c16b537SWarner Losh if (iSize >= (242)) /* RLE */ 1911*0c16b537SWarner Losh { 1912*0c16b537SWarner Losh static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; 1913*0c16b537SWarner Losh oSize = l[iSize-242]; 1914*0c16b537SWarner Losh memset(huffWeight, 1, hwSize); 1915*0c16b537SWarner Losh iSize = 0; 1916*0c16b537SWarner Losh } 1917*0c16b537SWarner Losh else /* Incompressible */ 1918*0c16b537SWarner Losh { 1919*0c16b537SWarner Losh oSize = iSize - 127; 1920*0c16b537SWarner Losh iSize = ((oSize+1)/2); 1921*0c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 1922*0c16b537SWarner Losh if (oSize >= hwSize) return ERROR(corruption_detected); 1923*0c16b537SWarner Losh ip += 1; 1924*0c16b537SWarner Losh for (n=0; n<oSize; n+=2) 1925*0c16b537SWarner Losh { 1926*0c16b537SWarner Losh huffWeight[n] = ip[n/2] >> 4; 1927*0c16b537SWarner Losh huffWeight[n+1] = ip[n/2] & 15; 1928*0c16b537SWarner Losh } 1929*0c16b537SWarner Losh } 1930*0c16b537SWarner Losh } 1931*0c16b537SWarner Losh else /* header compressed with FSE (normal case) */ 1932*0c16b537SWarner Losh { 1933*0c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 1934*0c16b537SWarner Losh oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ 1935*0c16b537SWarner Losh if (FSE_isError(oSize)) return oSize; 1936*0c16b537SWarner Losh } 1937*0c16b537SWarner Losh 1938*0c16b537SWarner Losh /* collect weight stats */ 1939*0c16b537SWarner Losh memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32)); 1940*0c16b537SWarner Losh weightTotal = 0; 1941*0c16b537SWarner Losh for (n=0; n<oSize; n++) 1942*0c16b537SWarner Losh { 1943*0c16b537SWarner Losh if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); 1944*0c16b537SWarner Losh rankStats[huffWeight[n]]++; 1945*0c16b537SWarner Losh weightTotal += (1 << huffWeight[n]) >> 1; 1946*0c16b537SWarner Losh } 1947*0c16b537SWarner Losh if (weightTotal == 0) return ERROR(corruption_detected); 1948*0c16b537SWarner Losh 1949*0c16b537SWarner Losh /* get last non-null symbol weight (implied, total must be 2^n) */ 1950*0c16b537SWarner Losh tableLog = BIT_highbit32(weightTotal) + 1; 1951*0c16b537SWarner Losh if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); 1952*0c16b537SWarner Losh { 1953*0c16b537SWarner Losh U32 total = 1 << tableLog; 1954*0c16b537SWarner Losh U32 rest = total - weightTotal; 1955*0c16b537SWarner Losh U32 verif = 1 << BIT_highbit32(rest); 1956*0c16b537SWarner Losh U32 lastWeight = BIT_highbit32(rest) + 1; 1957*0c16b537SWarner Losh if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ 1958*0c16b537SWarner Losh huffWeight[oSize] = (BYTE)lastWeight; 1959*0c16b537SWarner Losh rankStats[lastWeight]++; 1960*0c16b537SWarner Losh } 1961*0c16b537SWarner Losh 1962*0c16b537SWarner Losh /* check tree construction validity */ 1963*0c16b537SWarner Losh if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ 1964*0c16b537SWarner Losh 1965*0c16b537SWarner Losh /* results */ 1966*0c16b537SWarner Losh *nbSymbolsPtr = (U32)(oSize+1); 1967*0c16b537SWarner Losh *tableLogPtr = tableLog; 1968*0c16b537SWarner Losh return iSize+1; 1969*0c16b537SWarner Losh } 1970*0c16b537SWarner Losh 1971*0c16b537SWarner Losh 1972*0c16b537SWarner Losh /**************************/ 1973*0c16b537SWarner Losh /* single-symbol decoding */ 1974*0c16b537SWarner Losh /**************************/ 1975*0c16b537SWarner Losh 1976*0c16b537SWarner Losh static size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize) 1977*0c16b537SWarner Losh { 1978*0c16b537SWarner Losh BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; 1979*0c16b537SWarner Losh U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ 1980*0c16b537SWarner Losh U32 tableLog = 0; 1981*0c16b537SWarner Losh size_t iSize; 1982*0c16b537SWarner Losh U32 nbSymbols = 0; 1983*0c16b537SWarner Losh U32 n; 1984*0c16b537SWarner Losh U32 nextRankStart; 1985*0c16b537SWarner Losh void* const dtPtr = DTable + 1; 1986*0c16b537SWarner Losh HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; 1987*0c16b537SWarner Losh 1988*0c16b537SWarner Losh HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ 1989*0c16b537SWarner Losh //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ 1990*0c16b537SWarner Losh 1991*0c16b537SWarner Losh iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); 1992*0c16b537SWarner Losh if (HUF_isError(iSize)) return iSize; 1993*0c16b537SWarner Losh 1994*0c16b537SWarner Losh /* check result */ 1995*0c16b537SWarner Losh if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */ 1996*0c16b537SWarner Losh DTable[0] = (U16)tableLog; /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */ 1997*0c16b537SWarner Losh 1998*0c16b537SWarner Losh /* Prepare ranks */ 1999*0c16b537SWarner Losh nextRankStart = 0; 2000*0c16b537SWarner Losh for (n=1; n<=tableLog; n++) 2001*0c16b537SWarner Losh { 2002*0c16b537SWarner Losh U32 current = nextRankStart; 2003*0c16b537SWarner Losh nextRankStart += (rankVal[n] << (n-1)); 2004*0c16b537SWarner Losh rankVal[n] = current; 2005*0c16b537SWarner Losh } 2006*0c16b537SWarner Losh 2007*0c16b537SWarner Losh /* fill DTable */ 2008*0c16b537SWarner Losh for (n=0; n<nbSymbols; n++) 2009*0c16b537SWarner Losh { 2010*0c16b537SWarner Losh const U32 w = huffWeight[n]; 2011*0c16b537SWarner Losh const U32 length = (1 << w) >> 1; 2012*0c16b537SWarner Losh U32 i; 2013*0c16b537SWarner Losh HUF_DEltX2 D; 2014*0c16b537SWarner Losh D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); 2015*0c16b537SWarner Losh for (i = rankVal[w]; i < rankVal[w] + length; i++) 2016*0c16b537SWarner Losh dt[i] = D; 2017*0c16b537SWarner Losh rankVal[w] += length; 2018*0c16b537SWarner Losh } 2019*0c16b537SWarner Losh 2020*0c16b537SWarner Losh return iSize; 2021*0c16b537SWarner Losh } 2022*0c16b537SWarner Losh 2023*0c16b537SWarner Losh static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog) 2024*0c16b537SWarner Losh { 2025*0c16b537SWarner Losh const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ 2026*0c16b537SWarner Losh const BYTE c = dt[val].byte; 2027*0c16b537SWarner Losh BIT_skipBits(Dstream, dt[val].nbBits); 2028*0c16b537SWarner Losh return c; 2029*0c16b537SWarner Losh } 2030*0c16b537SWarner Losh 2031*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ 2032*0c16b537SWarner Losh *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog) 2033*0c16b537SWarner Losh 2034*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ 2035*0c16b537SWarner Losh if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ 2036*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) 2037*0c16b537SWarner Losh 2038*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ 2039*0c16b537SWarner Losh if (MEM_64bits()) \ 2040*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) 2041*0c16b537SWarner Losh 2042*0c16b537SWarner Losh static inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog) 2043*0c16b537SWarner Losh { 2044*0c16b537SWarner Losh BYTE* const pStart = p; 2045*0c16b537SWarner Losh 2046*0c16b537SWarner Losh /* up to 4 symbols at a time */ 2047*0c16b537SWarner Losh while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) 2048*0c16b537SWarner Losh { 2049*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(p, bitDPtr); 2050*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_1(p, bitDPtr); 2051*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(p, bitDPtr); 2052*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(p, bitDPtr); 2053*0c16b537SWarner Losh } 2054*0c16b537SWarner Losh 2055*0c16b537SWarner Losh /* closer to the end */ 2056*0c16b537SWarner Losh while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd)) 2057*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(p, bitDPtr); 2058*0c16b537SWarner Losh 2059*0c16b537SWarner Losh /* no more data to retrieve from bitstream, hence no need to reload */ 2060*0c16b537SWarner Losh while (p < pEnd) 2061*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(p, bitDPtr); 2062*0c16b537SWarner Losh 2063*0c16b537SWarner Losh return pEnd-pStart; 2064*0c16b537SWarner Losh } 2065*0c16b537SWarner Losh 2066*0c16b537SWarner Losh 2067*0c16b537SWarner Losh static size_t HUF_decompress4X2_usingDTable( 2068*0c16b537SWarner Losh void* dst, size_t dstSize, 2069*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize, 2070*0c16b537SWarner Losh const U16* DTable) 2071*0c16b537SWarner Losh { 2072*0c16b537SWarner Losh if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ 2073*0c16b537SWarner Losh 2074*0c16b537SWarner Losh { 2075*0c16b537SWarner Losh const BYTE* const istart = (const BYTE*) cSrc; 2076*0c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst; 2077*0c16b537SWarner Losh BYTE* const oend = ostart + dstSize; 2078*0c16b537SWarner Losh const void* const dtPtr = DTable; 2079*0c16b537SWarner Losh const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr) +1; 2080*0c16b537SWarner Losh const U32 dtLog = DTable[0]; 2081*0c16b537SWarner Losh size_t errorCode; 2082*0c16b537SWarner Losh 2083*0c16b537SWarner Losh /* Init */ 2084*0c16b537SWarner Losh BIT_DStream_t bitD1; 2085*0c16b537SWarner Losh BIT_DStream_t bitD2; 2086*0c16b537SWarner Losh BIT_DStream_t bitD3; 2087*0c16b537SWarner Losh BIT_DStream_t bitD4; 2088*0c16b537SWarner Losh const size_t length1 = MEM_readLE16(istart); 2089*0c16b537SWarner Losh const size_t length2 = MEM_readLE16(istart+2); 2090*0c16b537SWarner Losh const size_t length3 = MEM_readLE16(istart+4); 2091*0c16b537SWarner Losh size_t length4; 2092*0c16b537SWarner Losh const BYTE* const istart1 = istart + 6; /* jumpTable */ 2093*0c16b537SWarner Losh const BYTE* const istart2 = istart1 + length1; 2094*0c16b537SWarner Losh const BYTE* const istart3 = istart2 + length2; 2095*0c16b537SWarner Losh const BYTE* const istart4 = istart3 + length3; 2096*0c16b537SWarner Losh const size_t segmentSize = (dstSize+3) / 4; 2097*0c16b537SWarner Losh BYTE* const opStart2 = ostart + segmentSize; 2098*0c16b537SWarner Losh BYTE* const opStart3 = opStart2 + segmentSize; 2099*0c16b537SWarner Losh BYTE* const opStart4 = opStart3 + segmentSize; 2100*0c16b537SWarner Losh BYTE* op1 = ostart; 2101*0c16b537SWarner Losh BYTE* op2 = opStart2; 2102*0c16b537SWarner Losh BYTE* op3 = opStart3; 2103*0c16b537SWarner Losh BYTE* op4 = opStart4; 2104*0c16b537SWarner Losh U32 endSignal; 2105*0c16b537SWarner Losh 2106*0c16b537SWarner Losh length4 = cSrcSize - (length1 + length2 + length3 + 6); 2107*0c16b537SWarner Losh if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ 2108*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD1, istart1, length1); 2109*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2110*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD2, istart2, length2); 2111*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2112*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD3, istart3, length3); 2113*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2114*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD4, istart4, length4); 2115*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2116*0c16b537SWarner Losh 2117*0c16b537SWarner Losh /* 16-32 symbols per loop (4-8 symbols per stream) */ 2118*0c16b537SWarner Losh endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); 2119*0c16b537SWarner Losh for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) 2120*0c16b537SWarner Losh { 2121*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op1, &bitD1); 2122*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op2, &bitD2); 2123*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op3, &bitD3); 2124*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op4, &bitD4); 2125*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_1(op1, &bitD1); 2126*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_1(op2, &bitD2); 2127*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_1(op3, &bitD3); 2128*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_1(op4, &bitD4); 2129*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op1, &bitD1); 2130*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op2, &bitD2); 2131*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op3, &bitD3); 2132*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_2(op4, &bitD4); 2133*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(op1, &bitD1); 2134*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(op2, &bitD2); 2135*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(op3, &bitD3); 2136*0c16b537SWarner Losh HUF_DECODE_SYMBOLX2_0(op4, &bitD4); 2137*0c16b537SWarner Losh 2138*0c16b537SWarner Losh endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); 2139*0c16b537SWarner Losh } 2140*0c16b537SWarner Losh 2141*0c16b537SWarner Losh /* check corruption */ 2142*0c16b537SWarner Losh if (op1 > opStart2) return ERROR(corruption_detected); 2143*0c16b537SWarner Losh if (op2 > opStart3) return ERROR(corruption_detected); 2144*0c16b537SWarner Losh if (op3 > opStart4) return ERROR(corruption_detected); 2145*0c16b537SWarner Losh /* note : op4 supposed already verified within main loop */ 2146*0c16b537SWarner Losh 2147*0c16b537SWarner Losh /* finish bitStreams one by one */ 2148*0c16b537SWarner Losh HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); 2149*0c16b537SWarner Losh HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); 2150*0c16b537SWarner Losh HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); 2151*0c16b537SWarner Losh HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); 2152*0c16b537SWarner Losh 2153*0c16b537SWarner Losh /* check */ 2154*0c16b537SWarner Losh endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); 2155*0c16b537SWarner Losh if (!endSignal) return ERROR(corruption_detected); 2156*0c16b537SWarner Losh 2157*0c16b537SWarner Losh /* decoded size */ 2158*0c16b537SWarner Losh return dstSize; 2159*0c16b537SWarner Losh } 2160*0c16b537SWarner Losh } 2161*0c16b537SWarner Losh 2162*0c16b537SWarner Losh 2163*0c16b537SWarner Losh static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) 2164*0c16b537SWarner Losh { 2165*0c16b537SWarner Losh HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG); 2166*0c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc; 2167*0c16b537SWarner Losh size_t errorCode; 2168*0c16b537SWarner Losh 2169*0c16b537SWarner Losh errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize); 2170*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2171*0c16b537SWarner Losh if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); 2172*0c16b537SWarner Losh ip += errorCode; 2173*0c16b537SWarner Losh cSrcSize -= errorCode; 2174*0c16b537SWarner Losh 2175*0c16b537SWarner Losh return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable); 2176*0c16b537SWarner Losh } 2177*0c16b537SWarner Losh 2178*0c16b537SWarner Losh 2179*0c16b537SWarner Losh /***************************/ 2180*0c16b537SWarner Losh /* double-symbols decoding */ 2181*0c16b537SWarner Losh /***************************/ 2182*0c16b537SWarner Losh 2183*0c16b537SWarner Losh static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed, 2184*0c16b537SWarner Losh const U32* rankValOrigin, const int minWeight, 2185*0c16b537SWarner Losh const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, 2186*0c16b537SWarner Losh U32 nbBitsBaseline, U16 baseSeq) 2187*0c16b537SWarner Losh { 2188*0c16b537SWarner Losh HUF_DEltX4 DElt; 2189*0c16b537SWarner Losh U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; 2190*0c16b537SWarner Losh U32 s; 2191*0c16b537SWarner Losh 2192*0c16b537SWarner Losh /* get pre-calculated rankVal */ 2193*0c16b537SWarner Losh memcpy(rankVal, rankValOrigin, sizeof(rankVal)); 2194*0c16b537SWarner Losh 2195*0c16b537SWarner Losh /* fill skipped values */ 2196*0c16b537SWarner Losh if (minWeight>1) 2197*0c16b537SWarner Losh { 2198*0c16b537SWarner Losh U32 i, skipSize = rankVal[minWeight]; 2199*0c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), baseSeq); 2200*0c16b537SWarner Losh DElt.nbBits = (BYTE)(consumed); 2201*0c16b537SWarner Losh DElt.length = 1; 2202*0c16b537SWarner Losh for (i = 0; i < skipSize; i++) 2203*0c16b537SWarner Losh DTable[i] = DElt; 2204*0c16b537SWarner Losh } 2205*0c16b537SWarner Losh 2206*0c16b537SWarner Losh /* fill DTable */ 2207*0c16b537SWarner Losh for (s=0; s<sortedListSize; s++) /* note : sortedSymbols already skipped */ 2208*0c16b537SWarner Losh { 2209*0c16b537SWarner Losh const U32 symbol = sortedSymbols[s].symbol; 2210*0c16b537SWarner Losh const U32 weight = sortedSymbols[s].weight; 2211*0c16b537SWarner Losh const U32 nbBits = nbBitsBaseline - weight; 2212*0c16b537SWarner Losh const U32 length = 1 << (sizeLog-nbBits); 2213*0c16b537SWarner Losh const U32 start = rankVal[weight]; 2214*0c16b537SWarner Losh U32 i = start; 2215*0c16b537SWarner Losh const U32 end = start + length; 2216*0c16b537SWarner Losh 2217*0c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8))); 2218*0c16b537SWarner Losh DElt.nbBits = (BYTE)(nbBits + consumed); 2219*0c16b537SWarner Losh DElt.length = 2; 2220*0c16b537SWarner Losh do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */ 2221*0c16b537SWarner Losh 2222*0c16b537SWarner Losh rankVal[weight] += length; 2223*0c16b537SWarner Losh } 2224*0c16b537SWarner Losh } 2225*0c16b537SWarner Losh 2226*0c16b537SWarner Losh typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1]; 2227*0c16b537SWarner Losh 2228*0c16b537SWarner Losh static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog, 2229*0c16b537SWarner Losh const sortedSymbol_t* sortedList, const U32 sortedListSize, 2230*0c16b537SWarner Losh const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, 2231*0c16b537SWarner Losh const U32 nbBitsBaseline) 2232*0c16b537SWarner Losh { 2233*0c16b537SWarner Losh U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; 2234*0c16b537SWarner Losh const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ 2235*0c16b537SWarner Losh const U32 minBits = nbBitsBaseline - maxWeight; 2236*0c16b537SWarner Losh U32 s; 2237*0c16b537SWarner Losh 2238*0c16b537SWarner Losh memcpy(rankVal, rankValOrigin, sizeof(rankVal)); 2239*0c16b537SWarner Losh 2240*0c16b537SWarner Losh /* fill DTable */ 2241*0c16b537SWarner Losh for (s=0; s<sortedListSize; s++) 2242*0c16b537SWarner Losh { 2243*0c16b537SWarner Losh const U16 symbol = sortedList[s].symbol; 2244*0c16b537SWarner Losh const U32 weight = sortedList[s].weight; 2245*0c16b537SWarner Losh const U32 nbBits = nbBitsBaseline - weight; 2246*0c16b537SWarner Losh const U32 start = rankVal[weight]; 2247*0c16b537SWarner Losh const U32 length = 1 << (targetLog-nbBits); 2248*0c16b537SWarner Losh 2249*0c16b537SWarner Losh if (targetLog-nbBits >= minBits) /* enough room for a second symbol */ 2250*0c16b537SWarner Losh { 2251*0c16b537SWarner Losh U32 sortedRank; 2252*0c16b537SWarner Losh int minWeight = nbBits + scaleLog; 2253*0c16b537SWarner Losh if (minWeight < 1) minWeight = 1; 2254*0c16b537SWarner Losh sortedRank = rankStart[minWeight]; 2255*0c16b537SWarner Losh HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits, 2256*0c16b537SWarner Losh rankValOrigin[nbBits], minWeight, 2257*0c16b537SWarner Losh sortedList+sortedRank, sortedListSize-sortedRank, 2258*0c16b537SWarner Losh nbBitsBaseline, symbol); 2259*0c16b537SWarner Losh } 2260*0c16b537SWarner Losh else 2261*0c16b537SWarner Losh { 2262*0c16b537SWarner Losh U32 i; 2263*0c16b537SWarner Losh const U32 end = start + length; 2264*0c16b537SWarner Losh HUF_DEltX4 DElt; 2265*0c16b537SWarner Losh 2266*0c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), symbol); 2267*0c16b537SWarner Losh DElt.nbBits = (BYTE)(nbBits); 2268*0c16b537SWarner Losh DElt.length = 1; 2269*0c16b537SWarner Losh for (i = start; i < end; i++) 2270*0c16b537SWarner Losh DTable[i] = DElt; 2271*0c16b537SWarner Losh } 2272*0c16b537SWarner Losh rankVal[weight] += length; 2273*0c16b537SWarner Losh } 2274*0c16b537SWarner Losh } 2275*0c16b537SWarner Losh 2276*0c16b537SWarner Losh static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize) 2277*0c16b537SWarner Losh { 2278*0c16b537SWarner Losh BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; 2279*0c16b537SWarner Losh sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; 2280*0c16b537SWarner Losh U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; 2281*0c16b537SWarner Losh U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; 2282*0c16b537SWarner Losh U32* const rankStart = rankStart0+1; 2283*0c16b537SWarner Losh rankVal_t rankVal; 2284*0c16b537SWarner Losh U32 tableLog, maxW, sizeOfSort, nbSymbols; 2285*0c16b537SWarner Losh const U32 memLog = DTable[0]; 2286*0c16b537SWarner Losh size_t iSize; 2287*0c16b537SWarner Losh void* dtPtr = DTable; 2288*0c16b537SWarner Losh HUF_DEltX4* const dt = ((HUF_DEltX4*)dtPtr) + 1; 2289*0c16b537SWarner Losh 2290*0c16b537SWarner Losh HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */ 2291*0c16b537SWarner Losh if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); 2292*0c16b537SWarner Losh //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ 2293*0c16b537SWarner Losh 2294*0c16b537SWarner Losh iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); 2295*0c16b537SWarner Losh if (HUF_isError(iSize)) return iSize; 2296*0c16b537SWarner Losh 2297*0c16b537SWarner Losh /* check result */ 2298*0c16b537SWarner Losh if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ 2299*0c16b537SWarner Losh 2300*0c16b537SWarner Losh /* find maxWeight */ 2301*0c16b537SWarner Losh for (maxW = tableLog; rankStats[maxW]==0; maxW--) 2302*0c16b537SWarner Losh { if (!maxW) return ERROR(GENERIC); } /* necessarily finds a solution before maxW==0 */ 2303*0c16b537SWarner Losh 2304*0c16b537SWarner Losh /* Get start index of each weight */ 2305*0c16b537SWarner Losh { 2306*0c16b537SWarner Losh U32 w, nextRankStart = 0; 2307*0c16b537SWarner Losh for (w=1; w<=maxW; w++) 2308*0c16b537SWarner Losh { 2309*0c16b537SWarner Losh U32 current = nextRankStart; 2310*0c16b537SWarner Losh nextRankStart += rankStats[w]; 2311*0c16b537SWarner Losh rankStart[w] = current; 2312*0c16b537SWarner Losh } 2313*0c16b537SWarner Losh rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ 2314*0c16b537SWarner Losh sizeOfSort = nextRankStart; 2315*0c16b537SWarner Losh } 2316*0c16b537SWarner Losh 2317*0c16b537SWarner Losh /* sort symbols by weight */ 2318*0c16b537SWarner Losh { 2319*0c16b537SWarner Losh U32 s; 2320*0c16b537SWarner Losh for (s=0; s<nbSymbols; s++) 2321*0c16b537SWarner Losh { 2322*0c16b537SWarner Losh U32 w = weightList[s]; 2323*0c16b537SWarner Losh U32 r = rankStart[w]++; 2324*0c16b537SWarner Losh sortedSymbol[r].symbol = (BYTE)s; 2325*0c16b537SWarner Losh sortedSymbol[r].weight = (BYTE)w; 2326*0c16b537SWarner Losh } 2327*0c16b537SWarner Losh rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ 2328*0c16b537SWarner Losh } 2329*0c16b537SWarner Losh 2330*0c16b537SWarner Losh /* Build rankVal */ 2331*0c16b537SWarner Losh { 2332*0c16b537SWarner Losh const U32 minBits = tableLog+1 - maxW; 2333*0c16b537SWarner Losh U32 nextRankVal = 0; 2334*0c16b537SWarner Losh U32 w, consumed; 2335*0c16b537SWarner Losh const int rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */ 2336*0c16b537SWarner Losh U32* rankVal0 = rankVal[0]; 2337*0c16b537SWarner Losh for (w=1; w<=maxW; w++) 2338*0c16b537SWarner Losh { 2339*0c16b537SWarner Losh U32 current = nextRankVal; 2340*0c16b537SWarner Losh nextRankVal += rankStats[w] << (w+rescale); 2341*0c16b537SWarner Losh rankVal0[w] = current; 2342*0c16b537SWarner Losh } 2343*0c16b537SWarner Losh for (consumed = minBits; consumed <= memLog - minBits; consumed++) 2344*0c16b537SWarner Losh { 2345*0c16b537SWarner Losh U32* rankValPtr = rankVal[consumed]; 2346*0c16b537SWarner Losh for (w = 1; w <= maxW; w++) 2347*0c16b537SWarner Losh { 2348*0c16b537SWarner Losh rankValPtr[w] = rankVal0[w] >> consumed; 2349*0c16b537SWarner Losh } 2350*0c16b537SWarner Losh } 2351*0c16b537SWarner Losh } 2352*0c16b537SWarner Losh 2353*0c16b537SWarner Losh HUF_fillDTableX4(dt, memLog, 2354*0c16b537SWarner Losh sortedSymbol, sizeOfSort, 2355*0c16b537SWarner Losh rankStart0, rankVal, maxW, 2356*0c16b537SWarner Losh tableLog+1); 2357*0c16b537SWarner Losh 2358*0c16b537SWarner Losh return iSize; 2359*0c16b537SWarner Losh } 2360*0c16b537SWarner Losh 2361*0c16b537SWarner Losh 2362*0c16b537SWarner Losh static U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) 2363*0c16b537SWarner Losh { 2364*0c16b537SWarner Losh const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ 2365*0c16b537SWarner Losh memcpy(op, dt+val, 2); 2366*0c16b537SWarner Losh BIT_skipBits(DStream, dt[val].nbBits); 2367*0c16b537SWarner Losh return dt[val].length; 2368*0c16b537SWarner Losh } 2369*0c16b537SWarner Losh 2370*0c16b537SWarner Losh static U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) 2371*0c16b537SWarner Losh { 2372*0c16b537SWarner Losh const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ 2373*0c16b537SWarner Losh memcpy(op, dt+val, 1); 2374*0c16b537SWarner Losh if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); 2375*0c16b537SWarner Losh else 2376*0c16b537SWarner Losh { 2377*0c16b537SWarner Losh if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) 2378*0c16b537SWarner Losh { 2379*0c16b537SWarner Losh BIT_skipBits(DStream, dt[val].nbBits); 2380*0c16b537SWarner Losh if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) 2381*0c16b537SWarner Losh DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ 2382*0c16b537SWarner Losh } 2383*0c16b537SWarner Losh } 2384*0c16b537SWarner Losh return 1; 2385*0c16b537SWarner Losh } 2386*0c16b537SWarner Losh 2387*0c16b537SWarner Losh 2388*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \ 2389*0c16b537SWarner Losh ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) 2390*0c16b537SWarner Losh 2391*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \ 2392*0c16b537SWarner Losh if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ 2393*0c16b537SWarner Losh ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) 2394*0c16b537SWarner Losh 2395*0c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \ 2396*0c16b537SWarner Losh if (MEM_64bits()) \ 2397*0c16b537SWarner Losh ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) 2398*0c16b537SWarner Losh 2399*0c16b537SWarner Losh static inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog) 2400*0c16b537SWarner Losh { 2401*0c16b537SWarner Losh BYTE* const pStart = p; 2402*0c16b537SWarner Losh 2403*0c16b537SWarner Losh /* up to 8 symbols at a time */ 2404*0c16b537SWarner Losh while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7)) 2405*0c16b537SWarner Losh { 2406*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(p, bitDPtr); 2407*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_1(p, bitDPtr); 2408*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(p, bitDPtr); 2409*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(p, bitDPtr); 2410*0c16b537SWarner Losh } 2411*0c16b537SWarner Losh 2412*0c16b537SWarner Losh /* closer to the end */ 2413*0c16b537SWarner Losh while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2)) 2414*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(p, bitDPtr); 2415*0c16b537SWarner Losh 2416*0c16b537SWarner Losh while (p <= pEnd-2) 2417*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ 2418*0c16b537SWarner Losh 2419*0c16b537SWarner Losh if (p < pEnd) 2420*0c16b537SWarner Losh p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog); 2421*0c16b537SWarner Losh 2422*0c16b537SWarner Losh return p-pStart; 2423*0c16b537SWarner Losh } 2424*0c16b537SWarner Losh 2425*0c16b537SWarner Losh static size_t HUF_decompress4X4_usingDTable( 2426*0c16b537SWarner Losh void* dst, size_t dstSize, 2427*0c16b537SWarner Losh const void* cSrc, size_t cSrcSize, 2428*0c16b537SWarner Losh const U32* DTable) 2429*0c16b537SWarner Losh { 2430*0c16b537SWarner Losh if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ 2431*0c16b537SWarner Losh 2432*0c16b537SWarner Losh { 2433*0c16b537SWarner Losh const BYTE* const istart = (const BYTE*) cSrc; 2434*0c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst; 2435*0c16b537SWarner Losh BYTE* const oend = ostart + dstSize; 2436*0c16b537SWarner Losh const void* const dtPtr = DTable; 2437*0c16b537SWarner Losh const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1; 2438*0c16b537SWarner Losh const U32 dtLog = DTable[0]; 2439*0c16b537SWarner Losh size_t errorCode; 2440*0c16b537SWarner Losh 2441*0c16b537SWarner Losh /* Init */ 2442*0c16b537SWarner Losh BIT_DStream_t bitD1; 2443*0c16b537SWarner Losh BIT_DStream_t bitD2; 2444*0c16b537SWarner Losh BIT_DStream_t bitD3; 2445*0c16b537SWarner Losh BIT_DStream_t bitD4; 2446*0c16b537SWarner Losh const size_t length1 = MEM_readLE16(istart); 2447*0c16b537SWarner Losh const size_t length2 = MEM_readLE16(istart+2); 2448*0c16b537SWarner Losh const size_t length3 = MEM_readLE16(istart+4); 2449*0c16b537SWarner Losh size_t length4; 2450*0c16b537SWarner Losh const BYTE* const istart1 = istart + 6; /* jumpTable */ 2451*0c16b537SWarner Losh const BYTE* const istart2 = istart1 + length1; 2452*0c16b537SWarner Losh const BYTE* const istart3 = istart2 + length2; 2453*0c16b537SWarner Losh const BYTE* const istart4 = istart3 + length3; 2454*0c16b537SWarner Losh const size_t segmentSize = (dstSize+3) / 4; 2455*0c16b537SWarner Losh BYTE* const opStart2 = ostart + segmentSize; 2456*0c16b537SWarner Losh BYTE* const opStart3 = opStart2 + segmentSize; 2457*0c16b537SWarner Losh BYTE* const opStart4 = opStart3 + segmentSize; 2458*0c16b537SWarner Losh BYTE* op1 = ostart; 2459*0c16b537SWarner Losh BYTE* op2 = opStart2; 2460*0c16b537SWarner Losh BYTE* op3 = opStart3; 2461*0c16b537SWarner Losh BYTE* op4 = opStart4; 2462*0c16b537SWarner Losh U32 endSignal; 2463*0c16b537SWarner Losh 2464*0c16b537SWarner Losh length4 = cSrcSize - (length1 + length2 + length3 + 6); 2465*0c16b537SWarner Losh if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ 2466*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD1, istart1, length1); 2467*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2468*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD2, istart2, length2); 2469*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2470*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD3, istart3, length3); 2471*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2472*0c16b537SWarner Losh errorCode = BIT_initDStream(&bitD4, istart4, length4); 2473*0c16b537SWarner Losh if (HUF_isError(errorCode)) return errorCode; 2474*0c16b537SWarner Losh 2475*0c16b537SWarner Losh /* 16-32 symbols per loop (4-8 symbols per stream) */ 2476*0c16b537SWarner Losh endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); 2477*0c16b537SWarner Losh for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) 2478*0c16b537SWarner Losh { 2479*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op1, &bitD1); 2480*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op2, &bitD2); 2481*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op3, &bitD3); 2482*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op4, &bitD4); 2483*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_1(op1, &bitD1); 2484*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_1(op2, &bitD2); 2485*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_1(op3, &bitD3); 2486*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_1(op4, &bitD4); 2487*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op1, &bitD1); 2488*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op2, &bitD2); 2489*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op3, &bitD3); 2490*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_2(op4, &bitD4); 2491*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(op1, &bitD1); 2492*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(op2, &bitD2); 2493*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(op3, &bitD3); 2494*0c16b537SWarner Losh HUF_DECODE_SYMBOLX4_0(op4, &bitD4); 2495*0c16b537SWarner Losh 2496*0c16b537SWarner Losh endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); 2497*0c16b537SWarner Losh } 2498*0c16b537SWarner Losh 2499*0c16b537SWarner Losh /* check corruption */ 2500*0c16b537SWarner Losh if (op1 > opStart2) return ERROR(corruption_detected); 2501*0c16b537SWarner Losh if (op2 > opStart3) return ERROR(corruption_detected); 2502*0c16b537SWarner Losh if (op3 > opStart4) return ERROR(corruption_detected); 2503*0c16b537SWarner Losh /* note : op4 supposed already verified within main loop */ 2504*0c16b537SWarner Losh 2505*0c16b537SWarner Losh /* finish bitStreams one by one */ 2506*0c16b537SWarner Losh HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog); 2507*0c16b537SWarner Losh HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog); 2508*0c16b537SWarner Losh HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog); 2509*0c16b537SWarner Losh HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog); 2510*0c16b537SWarner Losh 2511*0c16b537SWarner Losh /* check */ 2512*0c16b537SWarner Losh endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); 2513*0c16b537SWarner Losh if (!endSignal) return ERROR(corruption_detected); 2514*0c16b537SWarner Losh 2515*0c16b537SWarner Losh /* decoded size */ 2516*0c16b537SWarner Losh return dstSize; 2517*0c16b537SWarner Losh } 2518*0c16b537SWarner Losh } 2519*0c16b537SWarner Losh 2520*0c16b537SWarner Losh 2521*0c16b537SWarner Losh static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) 2522*0c16b537SWarner Losh { 2523*0c16b537SWarner Losh HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG); 2524*0c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc; 2525*0c16b537SWarner Losh 2526*0c16b537SWarner Losh size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize); 2527*0c16b537SWarner Losh if (HUF_isError(hSize)) return hSize; 2528*0c16b537SWarner Losh if (hSize >= cSrcSize) return ERROR(srcSize_wrong); 2529*0c16b537SWarner Losh ip += hSize; 2530*0c16b537SWarner Losh cSrcSize -= hSize; 2531*0c16b537SWarner Losh 2532*0c16b537SWarner Losh return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable); 2533*0c16b537SWarner Losh } 2534*0c16b537SWarner Losh 2535*0c16b537SWarner Losh 2536*0c16b537SWarner Losh /**********************************/ 2537*0c16b537SWarner Losh /* Generic decompression selector */ 2538*0c16b537SWarner Losh /**********************************/ 2539*0c16b537SWarner Losh 2540*0c16b537SWarner Losh typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t; 2541*0c16b537SWarner Losh static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = 2542*0c16b537SWarner Losh { 2543*0c16b537SWarner Losh /* single, double, quad */ 2544*0c16b537SWarner Losh {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */ 2545*0c16b537SWarner Losh {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */ 2546*0c16b537SWarner Losh {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */ 2547*0c16b537SWarner Losh {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */ 2548*0c16b537SWarner Losh {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */ 2549*0c16b537SWarner Losh {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */ 2550*0c16b537SWarner Losh {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */ 2551*0c16b537SWarner Losh {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */ 2552*0c16b537SWarner Losh {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */ 2553*0c16b537SWarner Losh {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */ 2554*0c16b537SWarner Losh {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */ 2555*0c16b537SWarner Losh {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */ 2556*0c16b537SWarner Losh {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */ 2557*0c16b537SWarner Losh {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */ 2558*0c16b537SWarner Losh {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */ 2559*0c16b537SWarner Losh {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */ 2560*0c16b537SWarner Losh }; 2561*0c16b537SWarner Losh 2562*0c16b537SWarner Losh typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); 2563*0c16b537SWarner Losh 2564*0c16b537SWarner Losh static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) 2565*0c16b537SWarner Losh { 2566*0c16b537SWarner Losh static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL }; 2567*0c16b537SWarner Losh /* estimate decompression time */ 2568*0c16b537SWarner Losh U32 Q; 2569*0c16b537SWarner Losh const U32 D256 = (U32)(dstSize >> 8); 2570*0c16b537SWarner Losh U32 Dtime[3]; 2571*0c16b537SWarner Losh U32 algoNb = 0; 2572*0c16b537SWarner Losh int n; 2573*0c16b537SWarner Losh 2574*0c16b537SWarner Losh /* validation checks */ 2575*0c16b537SWarner Losh if (dstSize == 0) return ERROR(dstSize_tooSmall); 2576*0c16b537SWarner Losh if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ 2577*0c16b537SWarner Losh if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ 2578*0c16b537SWarner Losh if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ 2579*0c16b537SWarner Losh 2580*0c16b537SWarner Losh /* decoder timing evaluation */ 2581*0c16b537SWarner Losh Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */ 2582*0c16b537SWarner Losh for (n=0; n<3; n++) 2583*0c16b537SWarner Losh Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256); 2584*0c16b537SWarner Losh 2585*0c16b537SWarner Losh Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ 2586*0c16b537SWarner Losh 2587*0c16b537SWarner Losh if (Dtime[1] < Dtime[0]) algoNb = 1; 2588*0c16b537SWarner Losh 2589*0c16b537SWarner Losh return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); 2590*0c16b537SWarner Losh 2591*0c16b537SWarner Losh //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */ 2592*0c16b537SWarner Losh //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */ 2593*0c16b537SWarner Losh //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize); /* multi-streams quad-symbols decoding */ 2594*0c16b537SWarner Losh } 2595*0c16b537SWarner Losh 2596*0c16b537SWarner Losh 2597*0c16b537SWarner Losh 2598*0c16b537SWarner Losh #endif /* ZSTD_CCOMMON_H_MODULE */ 2599*0c16b537SWarner Losh 2600*0c16b537SWarner Losh 2601*0c16b537SWarner Losh /* 2602*0c16b537SWarner Losh zstd - decompression module fo v0.4 legacy format 2603*0c16b537SWarner Losh Copyright (C) 2015-2016, Yann Collet. 2604*0c16b537SWarner Losh 2605*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 2606*0c16b537SWarner Losh 2607*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 2608*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 2609*0c16b537SWarner Losh met: 2610*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 2611*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 2612*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 2613*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 2614*0c16b537SWarner Losh in the documentation and/or other materials provided with the 2615*0c16b537SWarner Losh distribution. 2616*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2617*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2618*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2619*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2620*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2621*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2622*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2623*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2624*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2625*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2626*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2627*0c16b537SWarner Losh 2628*0c16b537SWarner Losh You can contact the author at : 2629*0c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd 2630*0c16b537SWarner Losh - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c 2631*0c16b537SWarner Losh */ 2632*0c16b537SWarner Losh 2633*0c16b537SWarner Losh /* *************************************************************** 2634*0c16b537SWarner Losh * Tuning parameters 2635*0c16b537SWarner Losh *****************************************************************/ 2636*0c16b537SWarner Losh /*! 2637*0c16b537SWarner Losh * HEAPMODE : 2638*0c16b537SWarner Losh * Select how default decompression function ZSTD_decompress() will allocate memory, 2639*0c16b537SWarner Losh * in memory stack (0), or in memory heap (1, requires malloc()) 2640*0c16b537SWarner Losh */ 2641*0c16b537SWarner Losh #ifndef ZSTD_HEAPMODE 2642*0c16b537SWarner Losh # define ZSTD_HEAPMODE 1 2643*0c16b537SWarner Losh #endif 2644*0c16b537SWarner Losh 2645*0c16b537SWarner Losh 2646*0c16b537SWarner Losh /* ******************************************************* 2647*0c16b537SWarner Losh * Includes 2648*0c16b537SWarner Losh *********************************************************/ 2649*0c16b537SWarner Losh #include <stdlib.h> /* calloc */ 2650*0c16b537SWarner Losh #include <string.h> /* memcpy, memmove */ 2651*0c16b537SWarner Losh #include <stdio.h> /* debug : printf */ 2652*0c16b537SWarner Losh 2653*0c16b537SWarner Losh 2654*0c16b537SWarner Losh /* ******************************************************* 2655*0c16b537SWarner Losh * Compiler specifics 2656*0c16b537SWarner Losh *********************************************************/ 2657*0c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */ 2658*0c16b537SWarner Losh # include <intrin.h> /* For Visual 2005 */ 2659*0c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 2660*0c16b537SWarner Losh # pragma warning(disable : 4324) /* disable: C4324: padded structure */ 2661*0c16b537SWarner Losh #endif 2662*0c16b537SWarner Losh 2663*0c16b537SWarner Losh 2664*0c16b537SWarner Losh /* ************************************* 2665*0c16b537SWarner Losh * Local types 2666*0c16b537SWarner Losh ***************************************/ 2667*0c16b537SWarner Losh typedef struct 2668*0c16b537SWarner Losh { 2669*0c16b537SWarner Losh blockType_t blockType; 2670*0c16b537SWarner Losh U32 origSize; 2671*0c16b537SWarner Losh } blockProperties_t; 2672*0c16b537SWarner Losh 2673*0c16b537SWarner Losh 2674*0c16b537SWarner Losh /* ******************************************************* 2675*0c16b537SWarner Losh * Memory operations 2676*0c16b537SWarner Losh **********************************************************/ 2677*0c16b537SWarner Losh static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } 2678*0c16b537SWarner Losh 2679*0c16b537SWarner Losh 2680*0c16b537SWarner Losh /* ************************************* 2681*0c16b537SWarner Losh * Error Management 2682*0c16b537SWarner Losh ***************************************/ 2683*0c16b537SWarner Losh 2684*0c16b537SWarner Losh /*! ZSTD_isError 2685*0c16b537SWarner Losh * tells if a return value is an error code */ 2686*0c16b537SWarner Losh static unsigned ZSTD_isError(size_t code) { return ERR_isError(code); } 2687*0c16b537SWarner Losh 2688*0c16b537SWarner Losh 2689*0c16b537SWarner Losh /* ************************************************************* 2690*0c16b537SWarner Losh * Context management 2691*0c16b537SWarner Losh ***************************************************************/ 2692*0c16b537SWarner Losh typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, 2693*0c16b537SWarner Losh ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTD_dStage; 2694*0c16b537SWarner Losh 2695*0c16b537SWarner Losh struct ZSTDv04_Dctx_s 2696*0c16b537SWarner Losh { 2697*0c16b537SWarner Losh U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; 2698*0c16b537SWarner Losh U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; 2699*0c16b537SWarner Losh U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; 2700*0c16b537SWarner Losh const void* previousDstEnd; 2701*0c16b537SWarner Losh const void* base; 2702*0c16b537SWarner Losh const void* vBase; 2703*0c16b537SWarner Losh const void* dictEnd; 2704*0c16b537SWarner Losh size_t expected; 2705*0c16b537SWarner Losh size_t headerSize; 2706*0c16b537SWarner Losh ZSTD_parameters params; 2707*0c16b537SWarner Losh blockType_t bType; 2708*0c16b537SWarner Losh ZSTD_dStage stage; 2709*0c16b537SWarner Losh const BYTE* litPtr; 2710*0c16b537SWarner Losh size_t litSize; 2711*0c16b537SWarner Losh BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */]; 2712*0c16b537SWarner Losh BYTE headerBuffer[ZSTD_frameHeaderSize_max]; 2713*0c16b537SWarner Losh }; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */ 2714*0c16b537SWarner Losh 2715*0c16b537SWarner Losh static size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx) 2716*0c16b537SWarner Losh { 2717*0c16b537SWarner Losh dctx->expected = ZSTD_frameHeaderSize_min; 2718*0c16b537SWarner Losh dctx->stage = ZSTDds_getFrameHeaderSize; 2719*0c16b537SWarner Losh dctx->previousDstEnd = NULL; 2720*0c16b537SWarner Losh dctx->base = NULL; 2721*0c16b537SWarner Losh dctx->vBase = NULL; 2722*0c16b537SWarner Losh dctx->dictEnd = NULL; 2723*0c16b537SWarner Losh return 0; 2724*0c16b537SWarner Losh } 2725*0c16b537SWarner Losh 2726*0c16b537SWarner Losh static ZSTD_DCtx* ZSTD_createDCtx(void) 2727*0c16b537SWarner Losh { 2728*0c16b537SWarner Losh ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx)); 2729*0c16b537SWarner Losh if (dctx==NULL) return NULL; 2730*0c16b537SWarner Losh ZSTD_resetDCtx(dctx); 2731*0c16b537SWarner Losh return dctx; 2732*0c16b537SWarner Losh } 2733*0c16b537SWarner Losh 2734*0c16b537SWarner Losh static size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) 2735*0c16b537SWarner Losh { 2736*0c16b537SWarner Losh free(dctx); 2737*0c16b537SWarner Losh return 0; 2738*0c16b537SWarner Losh } 2739*0c16b537SWarner Losh 2740*0c16b537SWarner Losh 2741*0c16b537SWarner Losh /* ************************************************************* 2742*0c16b537SWarner Losh * Decompression section 2743*0c16b537SWarner Losh ***************************************************************/ 2744*0c16b537SWarner Losh /** ZSTD_decodeFrameHeader_Part1 2745*0c16b537SWarner Losh * decode the 1st part of the Frame Header, which tells Frame Header size. 2746*0c16b537SWarner Losh * srcSize must be == ZSTD_frameHeaderSize_min 2747*0c16b537SWarner Losh * @return : the full size of the Frame Header */ 2748*0c16b537SWarner Losh static size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize) 2749*0c16b537SWarner Losh { 2750*0c16b537SWarner Losh U32 magicNumber; 2751*0c16b537SWarner Losh if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); 2752*0c16b537SWarner Losh magicNumber = MEM_readLE32(src); 2753*0c16b537SWarner Losh if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); 2754*0c16b537SWarner Losh zc->headerSize = ZSTD_frameHeaderSize_min; 2755*0c16b537SWarner Losh return zc->headerSize; 2756*0c16b537SWarner Losh } 2757*0c16b537SWarner Losh 2758*0c16b537SWarner Losh 2759*0c16b537SWarner Losh static size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize) 2760*0c16b537SWarner Losh { 2761*0c16b537SWarner Losh U32 magicNumber; 2762*0c16b537SWarner Losh if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max; 2763*0c16b537SWarner Losh magicNumber = MEM_readLE32(src); 2764*0c16b537SWarner Losh if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); 2765*0c16b537SWarner Losh memset(params, 0, sizeof(*params)); 2766*0c16b537SWarner Losh params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN; 2767*0c16b537SWarner Losh if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported); /* reserved bits */ 2768*0c16b537SWarner Losh return 0; 2769*0c16b537SWarner Losh } 2770*0c16b537SWarner Losh 2771*0c16b537SWarner Losh /** ZSTD_decodeFrameHeader_Part2 2772*0c16b537SWarner Losh * decode the full Frame Header 2773*0c16b537SWarner Losh * srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1 2774*0c16b537SWarner Losh * @return : 0, or an error code, which can be tested using ZSTD_isError() */ 2775*0c16b537SWarner Losh static size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize) 2776*0c16b537SWarner Losh { 2777*0c16b537SWarner Losh size_t result; 2778*0c16b537SWarner Losh if (srcSize != zc->headerSize) return ERROR(srcSize_wrong); 2779*0c16b537SWarner Losh result = ZSTD_getFrameParams(&(zc->params), src, srcSize); 2780*0c16b537SWarner Losh if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported); 2781*0c16b537SWarner Losh return result; 2782*0c16b537SWarner Losh } 2783*0c16b537SWarner Losh 2784*0c16b537SWarner Losh 2785*0c16b537SWarner Losh static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr) 2786*0c16b537SWarner Losh { 2787*0c16b537SWarner Losh const BYTE* const in = (const BYTE* const)src; 2788*0c16b537SWarner Losh BYTE headerFlags; 2789*0c16b537SWarner Losh U32 cSize; 2790*0c16b537SWarner Losh 2791*0c16b537SWarner Losh if (srcSize < 3) return ERROR(srcSize_wrong); 2792*0c16b537SWarner Losh 2793*0c16b537SWarner Losh headerFlags = *in; 2794*0c16b537SWarner Losh cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16); 2795*0c16b537SWarner Losh 2796*0c16b537SWarner Losh bpPtr->blockType = (blockType_t)(headerFlags >> 6); 2797*0c16b537SWarner Losh bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0; 2798*0c16b537SWarner Losh 2799*0c16b537SWarner Losh if (bpPtr->blockType == bt_end) return 0; 2800*0c16b537SWarner Losh if (bpPtr->blockType == bt_rle) return 1; 2801*0c16b537SWarner Losh return cSize; 2802*0c16b537SWarner Losh } 2803*0c16b537SWarner Losh 2804*0c16b537SWarner Losh static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) 2805*0c16b537SWarner Losh { 2806*0c16b537SWarner Losh if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); 2807*0c16b537SWarner Losh memcpy(dst, src, srcSize); 2808*0c16b537SWarner Losh return srcSize; 2809*0c16b537SWarner Losh } 2810*0c16b537SWarner Losh 2811*0c16b537SWarner Losh 2812*0c16b537SWarner Losh /** ZSTD_decompressLiterals 2813*0c16b537SWarner Losh @return : nb of bytes read from src, or an error code*/ 2814*0c16b537SWarner Losh static size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr, 2815*0c16b537SWarner Losh const void* src, size_t srcSize) 2816*0c16b537SWarner Losh { 2817*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)src; 2818*0c16b537SWarner Losh 2819*0c16b537SWarner Losh const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */ 2820*0c16b537SWarner Losh const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */ 2821*0c16b537SWarner Losh 2822*0c16b537SWarner Losh if (litSize > *maxDstSizePtr) return ERROR(corruption_detected); 2823*0c16b537SWarner Losh if (litCSize + 5 > srcSize) return ERROR(corruption_detected); 2824*0c16b537SWarner Losh 2825*0c16b537SWarner Losh if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected); 2826*0c16b537SWarner Losh 2827*0c16b537SWarner Losh *maxDstSizePtr = litSize; 2828*0c16b537SWarner Losh return litCSize + 5; 2829*0c16b537SWarner Losh } 2830*0c16b537SWarner Losh 2831*0c16b537SWarner Losh 2832*0c16b537SWarner Losh /** ZSTD_decodeLiteralsBlock 2833*0c16b537SWarner Losh @return : nb of bytes read from src (< srcSize ) */ 2834*0c16b537SWarner Losh static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, 2835*0c16b537SWarner Losh const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ 2836*0c16b537SWarner Losh { 2837*0c16b537SWarner Losh const BYTE* const istart = (const BYTE*) src; 2838*0c16b537SWarner Losh 2839*0c16b537SWarner Losh /* any compressed block with literals segment must be at least this size */ 2840*0c16b537SWarner Losh if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected); 2841*0c16b537SWarner Losh 2842*0c16b537SWarner Losh switch(*istart & 3) 2843*0c16b537SWarner Losh { 2844*0c16b537SWarner Losh /* compressed */ 2845*0c16b537SWarner Losh case 0: 2846*0c16b537SWarner Losh { 2847*0c16b537SWarner Losh size_t litSize = BLOCKSIZE; 2848*0c16b537SWarner Losh const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize); 2849*0c16b537SWarner Losh dctx->litPtr = dctx->litBuffer; 2850*0c16b537SWarner Losh dctx->litSize = litSize; 2851*0c16b537SWarner Losh memset(dctx->litBuffer + dctx->litSize, 0, 8); 2852*0c16b537SWarner Losh return readSize; /* works if it's an error too */ 2853*0c16b537SWarner Losh } 2854*0c16b537SWarner Losh case IS_RAW: 2855*0c16b537SWarner Losh { 2856*0c16b537SWarner Losh const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */ 2857*0c16b537SWarner Losh if (litSize > srcSize-11) /* risk of reading too far with wildcopy */ 2858*0c16b537SWarner Losh { 2859*0c16b537SWarner Losh if (litSize > srcSize-3) return ERROR(corruption_detected); 2860*0c16b537SWarner Losh memcpy(dctx->litBuffer, istart, litSize); 2861*0c16b537SWarner Losh dctx->litPtr = dctx->litBuffer; 2862*0c16b537SWarner Losh dctx->litSize = litSize; 2863*0c16b537SWarner Losh memset(dctx->litBuffer + dctx->litSize, 0, 8); 2864*0c16b537SWarner Losh return litSize+3; 2865*0c16b537SWarner Losh } 2866*0c16b537SWarner Losh /* direct reference into compressed stream */ 2867*0c16b537SWarner Losh dctx->litPtr = istart+3; 2868*0c16b537SWarner Losh dctx->litSize = litSize; 2869*0c16b537SWarner Losh return litSize+3; } 2870*0c16b537SWarner Losh case IS_RLE: 2871*0c16b537SWarner Losh { 2872*0c16b537SWarner Losh const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */ 2873*0c16b537SWarner Losh if (litSize > BLOCKSIZE) return ERROR(corruption_detected); 2874*0c16b537SWarner Losh memset(dctx->litBuffer, istart[3], litSize + 8); 2875*0c16b537SWarner Losh dctx->litPtr = dctx->litBuffer; 2876*0c16b537SWarner Losh dctx->litSize = litSize; 2877*0c16b537SWarner Losh return 4; 2878*0c16b537SWarner Losh } 2879*0c16b537SWarner Losh default: 2880*0c16b537SWarner Losh return ERROR(corruption_detected); /* forbidden nominal case */ 2881*0c16b537SWarner Losh } 2882*0c16b537SWarner Losh } 2883*0c16b537SWarner Losh 2884*0c16b537SWarner Losh 2885*0c16b537SWarner Losh static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr, 2886*0c16b537SWarner Losh FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb, 2887*0c16b537SWarner Losh const void* src, size_t srcSize) 2888*0c16b537SWarner Losh { 2889*0c16b537SWarner Losh const BYTE* const istart = (const BYTE* const)src; 2890*0c16b537SWarner Losh const BYTE* ip = istart; 2891*0c16b537SWarner Losh const BYTE* const iend = istart + srcSize; 2892*0c16b537SWarner Losh U32 LLtype, Offtype, MLtype; 2893*0c16b537SWarner Losh U32 LLlog, Offlog, MLlog; 2894*0c16b537SWarner Losh size_t dumpsLength; 2895*0c16b537SWarner Losh 2896*0c16b537SWarner Losh /* check */ 2897*0c16b537SWarner Losh if (srcSize < 5) return ERROR(srcSize_wrong); 2898*0c16b537SWarner Losh 2899*0c16b537SWarner Losh /* SeqHead */ 2900*0c16b537SWarner Losh *nbSeq = MEM_readLE16(ip); ip+=2; 2901*0c16b537SWarner Losh LLtype = *ip >> 6; 2902*0c16b537SWarner Losh Offtype = (*ip >> 4) & 3; 2903*0c16b537SWarner Losh MLtype = (*ip >> 2) & 3; 2904*0c16b537SWarner Losh if (*ip & 2) 2905*0c16b537SWarner Losh { 2906*0c16b537SWarner Losh dumpsLength = ip[2]; 2907*0c16b537SWarner Losh dumpsLength += ip[1] << 8; 2908*0c16b537SWarner Losh ip += 3; 2909*0c16b537SWarner Losh } 2910*0c16b537SWarner Losh else 2911*0c16b537SWarner Losh { 2912*0c16b537SWarner Losh dumpsLength = ip[1]; 2913*0c16b537SWarner Losh dumpsLength += (ip[0] & 1) << 8; 2914*0c16b537SWarner Losh ip += 2; 2915*0c16b537SWarner Losh } 2916*0c16b537SWarner Losh *dumpsPtr = ip; 2917*0c16b537SWarner Losh ip += dumpsLength; 2918*0c16b537SWarner Losh *dumpsLengthPtr = dumpsLength; 2919*0c16b537SWarner Losh 2920*0c16b537SWarner Losh /* check */ 2921*0c16b537SWarner Losh if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */ 2922*0c16b537SWarner Losh 2923*0c16b537SWarner Losh /* sequences */ 2924*0c16b537SWarner Losh { 2925*0c16b537SWarner Losh S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */ 2926*0c16b537SWarner Losh size_t headerSize; 2927*0c16b537SWarner Losh 2928*0c16b537SWarner Losh /* Build DTables */ 2929*0c16b537SWarner Losh switch(LLtype) 2930*0c16b537SWarner Losh { 2931*0c16b537SWarner Losh case bt_rle : 2932*0c16b537SWarner Losh LLlog = 0; 2933*0c16b537SWarner Losh FSE_buildDTable_rle(DTableLL, *ip++); break; 2934*0c16b537SWarner Losh case bt_raw : 2935*0c16b537SWarner Losh LLlog = LLbits; 2936*0c16b537SWarner Losh FSE_buildDTable_raw(DTableLL, LLbits); break; 2937*0c16b537SWarner Losh default : 2938*0c16b537SWarner Losh { U32 max = MaxLL; 2939*0c16b537SWarner Losh headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip); 2940*0c16b537SWarner Losh if (FSE_isError(headerSize)) return ERROR(GENERIC); 2941*0c16b537SWarner Losh if (LLlog > LLFSELog) return ERROR(corruption_detected); 2942*0c16b537SWarner Losh ip += headerSize; 2943*0c16b537SWarner Losh FSE_buildDTable(DTableLL, norm, max, LLlog); 2944*0c16b537SWarner Losh } } 2945*0c16b537SWarner Losh 2946*0c16b537SWarner Losh switch(Offtype) 2947*0c16b537SWarner Losh { 2948*0c16b537SWarner Losh case bt_rle : 2949*0c16b537SWarner Losh Offlog = 0; 2950*0c16b537SWarner Losh if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ 2951*0c16b537SWarner Losh FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */ 2952*0c16b537SWarner Losh break; 2953*0c16b537SWarner Losh case bt_raw : 2954*0c16b537SWarner Losh Offlog = Offbits; 2955*0c16b537SWarner Losh FSE_buildDTable_raw(DTableOffb, Offbits); break; 2956*0c16b537SWarner Losh default : 2957*0c16b537SWarner Losh { U32 max = MaxOff; 2958*0c16b537SWarner Losh headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip); 2959*0c16b537SWarner Losh if (FSE_isError(headerSize)) return ERROR(GENERIC); 2960*0c16b537SWarner Losh if (Offlog > OffFSELog) return ERROR(corruption_detected); 2961*0c16b537SWarner Losh ip += headerSize; 2962*0c16b537SWarner Losh FSE_buildDTable(DTableOffb, norm, max, Offlog); 2963*0c16b537SWarner Losh } } 2964*0c16b537SWarner Losh 2965*0c16b537SWarner Losh switch(MLtype) 2966*0c16b537SWarner Losh { 2967*0c16b537SWarner Losh case bt_rle : 2968*0c16b537SWarner Losh MLlog = 0; 2969*0c16b537SWarner Losh if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ 2970*0c16b537SWarner Losh FSE_buildDTable_rle(DTableML, *ip++); break; 2971*0c16b537SWarner Losh case bt_raw : 2972*0c16b537SWarner Losh MLlog = MLbits; 2973*0c16b537SWarner Losh FSE_buildDTable_raw(DTableML, MLbits); break; 2974*0c16b537SWarner Losh default : 2975*0c16b537SWarner Losh { U32 max = MaxML; 2976*0c16b537SWarner Losh headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip); 2977*0c16b537SWarner Losh if (FSE_isError(headerSize)) return ERROR(GENERIC); 2978*0c16b537SWarner Losh if (MLlog > MLFSELog) return ERROR(corruption_detected); 2979*0c16b537SWarner Losh ip += headerSize; 2980*0c16b537SWarner Losh FSE_buildDTable(DTableML, norm, max, MLlog); 2981*0c16b537SWarner Losh } } } 2982*0c16b537SWarner Losh 2983*0c16b537SWarner Losh return ip-istart; 2984*0c16b537SWarner Losh } 2985*0c16b537SWarner Losh 2986*0c16b537SWarner Losh 2987*0c16b537SWarner Losh typedef struct { 2988*0c16b537SWarner Losh size_t litLength; 2989*0c16b537SWarner Losh size_t offset; 2990*0c16b537SWarner Losh size_t matchLength; 2991*0c16b537SWarner Losh } seq_t; 2992*0c16b537SWarner Losh 2993*0c16b537SWarner Losh typedef struct { 2994*0c16b537SWarner Losh BIT_DStream_t DStream; 2995*0c16b537SWarner Losh FSE_DState_t stateLL; 2996*0c16b537SWarner Losh FSE_DState_t stateOffb; 2997*0c16b537SWarner Losh FSE_DState_t stateML; 2998*0c16b537SWarner Losh size_t prevOffset; 2999*0c16b537SWarner Losh const BYTE* dumps; 3000*0c16b537SWarner Losh const BYTE* dumpsEnd; 3001*0c16b537SWarner Losh } seqState_t; 3002*0c16b537SWarner Losh 3003*0c16b537SWarner Losh 3004*0c16b537SWarner Losh static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) 3005*0c16b537SWarner Losh { 3006*0c16b537SWarner Losh size_t litLength; 3007*0c16b537SWarner Losh size_t prevOffset; 3008*0c16b537SWarner Losh size_t offset; 3009*0c16b537SWarner Losh size_t matchLength; 3010*0c16b537SWarner Losh const BYTE* dumps = seqState->dumps; 3011*0c16b537SWarner Losh const BYTE* const de = seqState->dumpsEnd; 3012*0c16b537SWarner Losh 3013*0c16b537SWarner Losh /* Literal length */ 3014*0c16b537SWarner Losh litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); 3015*0c16b537SWarner Losh prevOffset = litLength ? seq->offset : seqState->prevOffset; 3016*0c16b537SWarner Losh if (litLength == MaxLL) { 3017*0c16b537SWarner Losh U32 add = *dumps++; 3018*0c16b537SWarner Losh if (add < 255) litLength += add; 3019*0c16b537SWarner Losh else { 3020*0c16b537SWarner Losh litLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); 3021*0c16b537SWarner Losh dumps += 3; 3022*0c16b537SWarner Losh } 3023*0c16b537SWarner Losh if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */ 3024*0c16b537SWarner Losh if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ 3025*0c16b537SWarner Losh } 3026*0c16b537SWarner Losh 3027*0c16b537SWarner Losh /* Offset */ 3028*0c16b537SWarner Losh { static const U32 offsetPrefix[MaxOff+1] = { 3029*0c16b537SWarner Losh 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256, 3030*0c16b537SWarner Losh 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 3031*0c16b537SWarner Losh 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 }; 3032*0c16b537SWarner Losh U32 offsetCode, nbBits; 3033*0c16b537SWarner Losh offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* <= maxOff, by table construction */ 3034*0c16b537SWarner Losh if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream)); 3035*0c16b537SWarner Losh nbBits = offsetCode - 1; 3036*0c16b537SWarner Losh if (offsetCode==0) nbBits = 0; /* cmove */ 3037*0c16b537SWarner Losh offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits); 3038*0c16b537SWarner Losh if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream)); 3039*0c16b537SWarner Losh if (offsetCode==0) offset = prevOffset; /* cmove */ 3040*0c16b537SWarner Losh if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */ 3041*0c16b537SWarner Losh } 3042*0c16b537SWarner Losh 3043*0c16b537SWarner Losh /* MatchLength */ 3044*0c16b537SWarner Losh matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); 3045*0c16b537SWarner Losh if (matchLength == MaxML) { 3046*0c16b537SWarner Losh U32 add = *dumps++; 3047*0c16b537SWarner Losh if (add < 255) matchLength += add; 3048*0c16b537SWarner Losh else { 3049*0c16b537SWarner Losh matchLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); 3050*0c16b537SWarner Losh dumps += 3; 3051*0c16b537SWarner Losh } 3052*0c16b537SWarner Losh if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */ 3053*0c16b537SWarner Losh if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ 3054*0c16b537SWarner Losh } 3055*0c16b537SWarner Losh matchLength += MINMATCH; 3056*0c16b537SWarner Losh 3057*0c16b537SWarner Losh /* save result */ 3058*0c16b537SWarner Losh seq->litLength = litLength; 3059*0c16b537SWarner Losh seq->offset = offset; 3060*0c16b537SWarner Losh seq->matchLength = matchLength; 3061*0c16b537SWarner Losh seqState->dumps = dumps; 3062*0c16b537SWarner Losh } 3063*0c16b537SWarner Losh 3064*0c16b537SWarner Losh 3065*0c16b537SWarner Losh static size_t ZSTD_execSequence(BYTE* op, 3066*0c16b537SWarner Losh BYTE* const oend, seq_t sequence, 3067*0c16b537SWarner Losh const BYTE** litPtr, const BYTE* const litLimit, 3068*0c16b537SWarner Losh const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd) 3069*0c16b537SWarner Losh { 3070*0c16b537SWarner Losh static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ 3071*0c16b537SWarner Losh static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ 3072*0c16b537SWarner Losh BYTE* const oLitEnd = op + sequence.litLength; 3073*0c16b537SWarner Losh const size_t sequenceLength = sequence.litLength + sequence.matchLength; 3074*0c16b537SWarner Losh BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ 3075*0c16b537SWarner Losh BYTE* const oend_8 = oend-8; 3076*0c16b537SWarner Losh const BYTE* const litEnd = *litPtr + sequence.litLength; 3077*0c16b537SWarner Losh const BYTE* match = oLitEnd - sequence.offset; 3078*0c16b537SWarner Losh 3079*0c16b537SWarner Losh /* check */ 3080*0c16b537SWarner Losh if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */ 3081*0c16b537SWarner Losh if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */ 3082*0c16b537SWarner Losh if (litEnd > litLimit) return ERROR(corruption_detected); /* risk read beyond lit buffer */ 3083*0c16b537SWarner Losh 3084*0c16b537SWarner Losh /* copy Literals */ 3085*0c16b537SWarner Losh ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */ 3086*0c16b537SWarner Losh op = oLitEnd; 3087*0c16b537SWarner Losh *litPtr = litEnd; /* update for next sequence */ 3088*0c16b537SWarner Losh 3089*0c16b537SWarner Losh /* copy Match */ 3090*0c16b537SWarner Losh if (sequence.offset > (size_t)(oLitEnd - base)) 3091*0c16b537SWarner Losh { 3092*0c16b537SWarner Losh /* offset beyond prefix */ 3093*0c16b537SWarner Losh if (sequence.offset > (size_t)(oLitEnd - vBase)) 3094*0c16b537SWarner Losh return ERROR(corruption_detected); 3095*0c16b537SWarner Losh match = dictEnd - (base-match); 3096*0c16b537SWarner Losh if (match + sequence.matchLength <= dictEnd) 3097*0c16b537SWarner Losh { 3098*0c16b537SWarner Losh memmove(oLitEnd, match, sequence.matchLength); 3099*0c16b537SWarner Losh return sequenceLength; 3100*0c16b537SWarner Losh } 3101*0c16b537SWarner Losh /* span extDict & currentPrefixSegment */ 3102*0c16b537SWarner Losh { 3103*0c16b537SWarner Losh size_t length1 = dictEnd - match; 3104*0c16b537SWarner Losh memmove(oLitEnd, match, length1); 3105*0c16b537SWarner Losh op = oLitEnd + length1; 3106*0c16b537SWarner Losh sequence.matchLength -= length1; 3107*0c16b537SWarner Losh match = base; 3108*0c16b537SWarner Losh if (op > oend_8 || sequence.matchLength < MINMATCH) { 3109*0c16b537SWarner Losh while (op < oMatchEnd) *op++ = *match++; 3110*0c16b537SWarner Losh return sequenceLength; 3111*0c16b537SWarner Losh } 3112*0c16b537SWarner Losh } 3113*0c16b537SWarner Losh } 3114*0c16b537SWarner Losh /* Requirement: op <= oend_8 */ 3115*0c16b537SWarner Losh 3116*0c16b537SWarner Losh /* match within prefix */ 3117*0c16b537SWarner Losh if (sequence.offset < 8) { 3118*0c16b537SWarner Losh /* close range match, overlap */ 3119*0c16b537SWarner Losh const int sub2 = dec64table[sequence.offset]; 3120*0c16b537SWarner Losh op[0] = match[0]; 3121*0c16b537SWarner Losh op[1] = match[1]; 3122*0c16b537SWarner Losh op[2] = match[2]; 3123*0c16b537SWarner Losh op[3] = match[3]; 3124*0c16b537SWarner Losh match += dec32table[sequence.offset]; 3125*0c16b537SWarner Losh ZSTD_copy4(op+4, match); 3126*0c16b537SWarner Losh match -= sub2; 3127*0c16b537SWarner Losh } else { 3128*0c16b537SWarner Losh ZSTD_copy8(op, match); 3129*0c16b537SWarner Losh } 3130*0c16b537SWarner Losh op += 8; match += 8; 3131*0c16b537SWarner Losh 3132*0c16b537SWarner Losh if (oMatchEnd > oend-(16-MINMATCH)) 3133*0c16b537SWarner Losh { 3134*0c16b537SWarner Losh if (op < oend_8) 3135*0c16b537SWarner Losh { 3136*0c16b537SWarner Losh ZSTD_wildcopy(op, match, oend_8 - op); 3137*0c16b537SWarner Losh match += oend_8 - op; 3138*0c16b537SWarner Losh op = oend_8; 3139*0c16b537SWarner Losh } 3140*0c16b537SWarner Losh while (op < oMatchEnd) *op++ = *match++; 3141*0c16b537SWarner Losh } 3142*0c16b537SWarner Losh else 3143*0c16b537SWarner Losh { 3144*0c16b537SWarner Losh ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */ 3145*0c16b537SWarner Losh } 3146*0c16b537SWarner Losh return sequenceLength; 3147*0c16b537SWarner Losh } 3148*0c16b537SWarner Losh 3149*0c16b537SWarner Losh 3150*0c16b537SWarner Losh static size_t ZSTD_decompressSequences( 3151*0c16b537SWarner Losh ZSTD_DCtx* dctx, 3152*0c16b537SWarner Losh void* dst, size_t maxDstSize, 3153*0c16b537SWarner Losh const void* seqStart, size_t seqSize) 3154*0c16b537SWarner Losh { 3155*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)seqStart; 3156*0c16b537SWarner Losh const BYTE* const iend = ip + seqSize; 3157*0c16b537SWarner Losh BYTE* const ostart = (BYTE* const)dst; 3158*0c16b537SWarner Losh BYTE* op = ostart; 3159*0c16b537SWarner Losh BYTE* const oend = ostart + maxDstSize; 3160*0c16b537SWarner Losh size_t errorCode, dumpsLength; 3161*0c16b537SWarner Losh const BYTE* litPtr = dctx->litPtr; 3162*0c16b537SWarner Losh const BYTE* const litEnd = litPtr + dctx->litSize; 3163*0c16b537SWarner Losh int nbSeq; 3164*0c16b537SWarner Losh const BYTE* dumps; 3165*0c16b537SWarner Losh U32* DTableLL = dctx->LLTable; 3166*0c16b537SWarner Losh U32* DTableML = dctx->MLTable; 3167*0c16b537SWarner Losh U32* DTableOffb = dctx->OffTable; 3168*0c16b537SWarner Losh const BYTE* const base = (const BYTE*) (dctx->base); 3169*0c16b537SWarner Losh const BYTE* const vBase = (const BYTE*) (dctx->vBase); 3170*0c16b537SWarner Losh const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); 3171*0c16b537SWarner Losh 3172*0c16b537SWarner Losh /* Build Decoding Tables */ 3173*0c16b537SWarner Losh errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, 3174*0c16b537SWarner Losh DTableLL, DTableML, DTableOffb, 3175*0c16b537SWarner Losh ip, iend-ip); 3176*0c16b537SWarner Losh if (ZSTD_isError(errorCode)) return errorCode; 3177*0c16b537SWarner Losh ip += errorCode; 3178*0c16b537SWarner Losh 3179*0c16b537SWarner Losh /* Regen sequences */ 3180*0c16b537SWarner Losh { 3181*0c16b537SWarner Losh seq_t sequence; 3182*0c16b537SWarner Losh seqState_t seqState; 3183*0c16b537SWarner Losh 3184*0c16b537SWarner Losh memset(&sequence, 0, sizeof(sequence)); 3185*0c16b537SWarner Losh sequence.offset = 4; 3186*0c16b537SWarner Losh seqState.dumps = dumps; 3187*0c16b537SWarner Losh seqState.dumpsEnd = dumps + dumpsLength; 3188*0c16b537SWarner Losh seqState.prevOffset = 4; 3189*0c16b537SWarner Losh errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip); 3190*0c16b537SWarner Losh if (ERR_isError(errorCode)) return ERROR(corruption_detected); 3191*0c16b537SWarner Losh FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL); 3192*0c16b537SWarner Losh FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb); 3193*0c16b537SWarner Losh FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML); 3194*0c16b537SWarner Losh 3195*0c16b537SWarner Losh for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) 3196*0c16b537SWarner Losh { 3197*0c16b537SWarner Losh size_t oneSeqSize; 3198*0c16b537SWarner Losh nbSeq--; 3199*0c16b537SWarner Losh ZSTD_decodeSequence(&sequence, &seqState); 3200*0c16b537SWarner Losh oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd); 3201*0c16b537SWarner Losh if (ZSTD_isError(oneSeqSize)) return oneSeqSize; 3202*0c16b537SWarner Losh op += oneSeqSize; 3203*0c16b537SWarner Losh } 3204*0c16b537SWarner Losh 3205*0c16b537SWarner Losh /* check if reached exact end */ 3206*0c16b537SWarner Losh if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected); /* DStream should be entirely and exactly consumed; otherwise data is corrupted */ 3207*0c16b537SWarner Losh 3208*0c16b537SWarner Losh /* last literal segment */ 3209*0c16b537SWarner Losh { 3210*0c16b537SWarner Losh size_t lastLLSize = litEnd - litPtr; 3211*0c16b537SWarner Losh if (litPtr > litEnd) return ERROR(corruption_detected); 3212*0c16b537SWarner Losh if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); 3213*0c16b537SWarner Losh if (op != litPtr) memcpy(op, litPtr, lastLLSize); 3214*0c16b537SWarner Losh op += lastLLSize; 3215*0c16b537SWarner Losh } 3216*0c16b537SWarner Losh } 3217*0c16b537SWarner Losh 3218*0c16b537SWarner Losh return op-ostart; 3219*0c16b537SWarner Losh } 3220*0c16b537SWarner Losh 3221*0c16b537SWarner Losh 3222*0c16b537SWarner Losh static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) 3223*0c16b537SWarner Losh { 3224*0c16b537SWarner Losh if (dst != dctx->previousDstEnd) /* not contiguous */ 3225*0c16b537SWarner Losh { 3226*0c16b537SWarner Losh dctx->dictEnd = dctx->previousDstEnd; 3227*0c16b537SWarner Losh dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base)); 3228*0c16b537SWarner Losh dctx->base = dst; 3229*0c16b537SWarner Losh dctx->previousDstEnd = dst; 3230*0c16b537SWarner Losh } 3231*0c16b537SWarner Losh } 3232*0c16b537SWarner Losh 3233*0c16b537SWarner Losh 3234*0c16b537SWarner Losh static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, 3235*0c16b537SWarner Losh void* dst, size_t maxDstSize, 3236*0c16b537SWarner Losh const void* src, size_t srcSize) 3237*0c16b537SWarner Losh { 3238*0c16b537SWarner Losh /* blockType == blockCompressed */ 3239*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)src; 3240*0c16b537SWarner Losh 3241*0c16b537SWarner Losh /* Decode literals sub-block */ 3242*0c16b537SWarner Losh size_t litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); 3243*0c16b537SWarner Losh if (ZSTD_isError(litCSize)) return litCSize; 3244*0c16b537SWarner Losh ip += litCSize; 3245*0c16b537SWarner Losh srcSize -= litCSize; 3246*0c16b537SWarner Losh 3247*0c16b537SWarner Losh return ZSTD_decompressSequences(dctx, dst, maxDstSize, ip, srcSize); 3248*0c16b537SWarner Losh } 3249*0c16b537SWarner Losh 3250*0c16b537SWarner Losh 3251*0c16b537SWarner Losh static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx, 3252*0c16b537SWarner Losh void* dst, size_t maxDstSize, 3253*0c16b537SWarner Losh const void* src, size_t srcSize, 3254*0c16b537SWarner Losh const void* dict, size_t dictSize) 3255*0c16b537SWarner Losh { 3256*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)src; 3257*0c16b537SWarner Losh const BYTE* iend = ip + srcSize; 3258*0c16b537SWarner Losh BYTE* const ostart = (BYTE* const)dst; 3259*0c16b537SWarner Losh BYTE* op = ostart; 3260*0c16b537SWarner Losh BYTE* const oend = ostart + maxDstSize; 3261*0c16b537SWarner Losh size_t remainingSize = srcSize; 3262*0c16b537SWarner Losh blockProperties_t blockProperties; 3263*0c16b537SWarner Losh 3264*0c16b537SWarner Losh /* init */ 3265*0c16b537SWarner Losh ZSTD_resetDCtx(ctx); 3266*0c16b537SWarner Losh if (dict) 3267*0c16b537SWarner Losh { 3268*0c16b537SWarner Losh ZSTD_decompress_insertDictionary(ctx, dict, dictSize); 3269*0c16b537SWarner Losh ctx->dictEnd = ctx->previousDstEnd; 3270*0c16b537SWarner Losh ctx->vBase = (const char*)dst - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base)); 3271*0c16b537SWarner Losh ctx->base = dst; 3272*0c16b537SWarner Losh } 3273*0c16b537SWarner Losh else 3274*0c16b537SWarner Losh { 3275*0c16b537SWarner Losh ctx->vBase = ctx->base = ctx->dictEnd = dst; 3276*0c16b537SWarner Losh } 3277*0c16b537SWarner Losh 3278*0c16b537SWarner Losh /* Frame Header */ 3279*0c16b537SWarner Losh { 3280*0c16b537SWarner Losh size_t frameHeaderSize; 3281*0c16b537SWarner Losh if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); 3282*0c16b537SWarner Losh frameHeaderSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min); 3283*0c16b537SWarner Losh if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; 3284*0c16b537SWarner Losh if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); 3285*0c16b537SWarner Losh ip += frameHeaderSize; remainingSize -= frameHeaderSize; 3286*0c16b537SWarner Losh frameHeaderSize = ZSTD_decodeFrameHeader_Part2(ctx, src, frameHeaderSize); 3287*0c16b537SWarner Losh if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; 3288*0c16b537SWarner Losh } 3289*0c16b537SWarner Losh 3290*0c16b537SWarner Losh /* Loop on each block */ 3291*0c16b537SWarner Losh while (1) 3292*0c16b537SWarner Losh { 3293*0c16b537SWarner Losh size_t decodedSize=0; 3294*0c16b537SWarner Losh size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties); 3295*0c16b537SWarner Losh if (ZSTD_isError(cBlockSize)) return cBlockSize; 3296*0c16b537SWarner Losh 3297*0c16b537SWarner Losh ip += ZSTD_blockHeaderSize; 3298*0c16b537SWarner Losh remainingSize -= ZSTD_blockHeaderSize; 3299*0c16b537SWarner Losh if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); 3300*0c16b537SWarner Losh 3301*0c16b537SWarner Losh switch(blockProperties.blockType) 3302*0c16b537SWarner Losh { 3303*0c16b537SWarner Losh case bt_compressed: 3304*0c16b537SWarner Losh decodedSize = ZSTD_decompressBlock_internal(ctx, op, oend-op, ip, cBlockSize); 3305*0c16b537SWarner Losh break; 3306*0c16b537SWarner Losh case bt_raw : 3307*0c16b537SWarner Losh decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize); 3308*0c16b537SWarner Losh break; 3309*0c16b537SWarner Losh case bt_rle : 3310*0c16b537SWarner Losh return ERROR(GENERIC); /* not yet supported */ 3311*0c16b537SWarner Losh break; 3312*0c16b537SWarner Losh case bt_end : 3313*0c16b537SWarner Losh /* end of frame */ 3314*0c16b537SWarner Losh if (remainingSize) return ERROR(srcSize_wrong); 3315*0c16b537SWarner Losh break; 3316*0c16b537SWarner Losh default: 3317*0c16b537SWarner Losh return ERROR(GENERIC); /* impossible */ 3318*0c16b537SWarner Losh } 3319*0c16b537SWarner Losh if (cBlockSize == 0) break; /* bt_end */ 3320*0c16b537SWarner Losh 3321*0c16b537SWarner Losh if (ZSTD_isError(decodedSize)) return decodedSize; 3322*0c16b537SWarner Losh op += decodedSize; 3323*0c16b537SWarner Losh ip += cBlockSize; 3324*0c16b537SWarner Losh remainingSize -= cBlockSize; 3325*0c16b537SWarner Losh } 3326*0c16b537SWarner Losh 3327*0c16b537SWarner Losh return op-ostart; 3328*0c16b537SWarner Losh } 3329*0c16b537SWarner Losh 3330*0c16b537SWarner Losh static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) 3331*0c16b537SWarner Losh { 3332*0c16b537SWarner Losh const BYTE* ip = (const BYTE*)src; 3333*0c16b537SWarner Losh size_t remainingSize = srcSize; 3334*0c16b537SWarner Losh blockProperties_t blockProperties; 3335*0c16b537SWarner Losh 3336*0c16b537SWarner Losh /* Frame Header */ 3337*0c16b537SWarner Losh if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); 3338*0c16b537SWarner Losh if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); 3339*0c16b537SWarner Losh ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min; 3340*0c16b537SWarner Losh 3341*0c16b537SWarner Losh /* Loop on each block */ 3342*0c16b537SWarner Losh while (1) 3343*0c16b537SWarner Losh { 3344*0c16b537SWarner Losh size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); 3345*0c16b537SWarner Losh if (ZSTD_isError(cBlockSize)) return cBlockSize; 3346*0c16b537SWarner Losh 3347*0c16b537SWarner Losh ip += ZSTD_blockHeaderSize; 3348*0c16b537SWarner Losh remainingSize -= ZSTD_blockHeaderSize; 3349*0c16b537SWarner Losh if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); 3350*0c16b537SWarner Losh 3351*0c16b537SWarner Losh if (cBlockSize == 0) break; /* bt_end */ 3352*0c16b537SWarner Losh 3353*0c16b537SWarner Losh ip += cBlockSize; 3354*0c16b537SWarner Losh remainingSize -= cBlockSize; 3355*0c16b537SWarner Losh } 3356*0c16b537SWarner Losh 3357*0c16b537SWarner Losh return ip - (const BYTE*)src; 3358*0c16b537SWarner Losh } 3359*0c16b537SWarner Losh 3360*0c16b537SWarner Losh /* ****************************** 3361*0c16b537SWarner Losh * Streaming Decompression API 3362*0c16b537SWarner Losh ********************************/ 3363*0c16b537SWarner Losh static size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) 3364*0c16b537SWarner Losh { 3365*0c16b537SWarner Losh return dctx->expected; 3366*0c16b537SWarner Losh } 3367*0c16b537SWarner Losh 3368*0c16b537SWarner Losh static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) 3369*0c16b537SWarner Losh { 3370*0c16b537SWarner Losh /* Sanity check */ 3371*0c16b537SWarner Losh if (srcSize != ctx->expected) return ERROR(srcSize_wrong); 3372*0c16b537SWarner Losh ZSTD_checkContinuity(ctx, dst); 3373*0c16b537SWarner Losh 3374*0c16b537SWarner Losh /* Decompress : frame header; part 1 */ 3375*0c16b537SWarner Losh switch (ctx->stage) 3376*0c16b537SWarner Losh { 3377*0c16b537SWarner Losh case ZSTDds_getFrameHeaderSize : 3378*0c16b537SWarner Losh /* get frame header size */ 3379*0c16b537SWarner Losh if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */ 3380*0c16b537SWarner Losh ctx->headerSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min); 3381*0c16b537SWarner Losh if (ZSTD_isError(ctx->headerSize)) return ctx->headerSize; 3382*0c16b537SWarner Losh memcpy(ctx->headerBuffer, src, ZSTD_frameHeaderSize_min); 3383*0c16b537SWarner Losh if (ctx->headerSize > ZSTD_frameHeaderSize_min) return ERROR(GENERIC); /* impossible */ 3384*0c16b537SWarner Losh ctx->expected = 0; /* not necessary to copy more */ 3385*0c16b537SWarner Losh /* fallthrough */ 3386*0c16b537SWarner Losh case ZSTDds_decodeFrameHeader: 3387*0c16b537SWarner Losh /* get frame header */ 3388*0c16b537SWarner Losh { size_t const result = ZSTD_decodeFrameHeader_Part2(ctx, ctx->headerBuffer, ctx->headerSize); 3389*0c16b537SWarner Losh if (ZSTD_isError(result)) return result; 3390*0c16b537SWarner Losh ctx->expected = ZSTD_blockHeaderSize; 3391*0c16b537SWarner Losh ctx->stage = ZSTDds_decodeBlockHeader; 3392*0c16b537SWarner Losh return 0; 3393*0c16b537SWarner Losh } 3394*0c16b537SWarner Losh case ZSTDds_decodeBlockHeader: 3395*0c16b537SWarner Losh /* Decode block header */ 3396*0c16b537SWarner Losh { blockProperties_t bp; 3397*0c16b537SWarner Losh size_t const blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); 3398*0c16b537SWarner Losh if (ZSTD_isError(blockSize)) return blockSize; 3399*0c16b537SWarner Losh if (bp.blockType == bt_end) 3400*0c16b537SWarner Losh { 3401*0c16b537SWarner Losh ctx->expected = 0; 3402*0c16b537SWarner Losh ctx->stage = ZSTDds_getFrameHeaderSize; 3403*0c16b537SWarner Losh } 3404*0c16b537SWarner Losh else 3405*0c16b537SWarner Losh { 3406*0c16b537SWarner Losh ctx->expected = blockSize; 3407*0c16b537SWarner Losh ctx->bType = bp.blockType; 3408*0c16b537SWarner Losh ctx->stage = ZSTDds_decompressBlock; 3409*0c16b537SWarner Losh } 3410*0c16b537SWarner Losh return 0; 3411*0c16b537SWarner Losh } 3412*0c16b537SWarner Losh case ZSTDds_decompressBlock: 3413*0c16b537SWarner Losh { 3414*0c16b537SWarner Losh /* Decompress : block content */ 3415*0c16b537SWarner Losh size_t rSize; 3416*0c16b537SWarner Losh switch(ctx->bType) 3417*0c16b537SWarner Losh { 3418*0c16b537SWarner Losh case bt_compressed: 3419*0c16b537SWarner Losh rSize = ZSTD_decompressBlock_internal(ctx, dst, maxDstSize, src, srcSize); 3420*0c16b537SWarner Losh break; 3421*0c16b537SWarner Losh case bt_raw : 3422*0c16b537SWarner Losh rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize); 3423*0c16b537SWarner Losh break; 3424*0c16b537SWarner Losh case bt_rle : 3425*0c16b537SWarner Losh return ERROR(GENERIC); /* not yet handled */ 3426*0c16b537SWarner Losh break; 3427*0c16b537SWarner Losh case bt_end : /* should never happen (filtered at phase 1) */ 3428*0c16b537SWarner Losh rSize = 0; 3429*0c16b537SWarner Losh break; 3430*0c16b537SWarner Losh default: 3431*0c16b537SWarner Losh return ERROR(GENERIC); 3432*0c16b537SWarner Losh } 3433*0c16b537SWarner Losh ctx->stage = ZSTDds_decodeBlockHeader; 3434*0c16b537SWarner Losh ctx->expected = ZSTD_blockHeaderSize; 3435*0c16b537SWarner Losh ctx->previousDstEnd = (char*)dst + rSize; 3436*0c16b537SWarner Losh return rSize; 3437*0c16b537SWarner Losh } 3438*0c16b537SWarner Losh default: 3439*0c16b537SWarner Losh return ERROR(GENERIC); /* impossible */ 3440*0c16b537SWarner Losh } 3441*0c16b537SWarner Losh } 3442*0c16b537SWarner Losh 3443*0c16b537SWarner Losh 3444*0c16b537SWarner Losh static void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* dict, size_t dictSize) 3445*0c16b537SWarner Losh { 3446*0c16b537SWarner Losh ctx->dictEnd = ctx->previousDstEnd; 3447*0c16b537SWarner Losh ctx->vBase = (const char*)dict - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base)); 3448*0c16b537SWarner Losh ctx->base = dict; 3449*0c16b537SWarner Losh ctx->previousDstEnd = (const char*)dict + dictSize; 3450*0c16b537SWarner Losh } 3451*0c16b537SWarner Losh 3452*0c16b537SWarner Losh 3453*0c16b537SWarner Losh 3454*0c16b537SWarner Losh /* 3455*0c16b537SWarner Losh Buffered version of Zstd compression library 3456*0c16b537SWarner Losh Copyright (C) 2015, Yann Collet. 3457*0c16b537SWarner Losh 3458*0c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 3459*0c16b537SWarner Losh 3460*0c16b537SWarner Losh Redistribution and use in source and binary forms, with or without 3461*0c16b537SWarner Losh modification, are permitted provided that the following conditions are 3462*0c16b537SWarner Losh met: 3463*0c16b537SWarner Losh * Redistributions of source code must retain the above copyright 3464*0c16b537SWarner Losh notice, this list of conditions and the following disclaimer. 3465*0c16b537SWarner Losh * Redistributions in binary form must reproduce the above 3466*0c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer 3467*0c16b537SWarner Losh in the documentation and/or other materials provided with the 3468*0c16b537SWarner Losh distribution. 3469*0c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3470*0c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3471*0c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3472*0c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3473*0c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3474*0c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3475*0c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3476*0c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3477*0c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3478*0c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3479*0c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3480*0c16b537SWarner Losh 3481*0c16b537SWarner Losh You can contact the author at : 3482*0c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd 3483*0c16b537SWarner Losh - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c 3484*0c16b537SWarner Losh */ 3485*0c16b537SWarner Losh 3486*0c16b537SWarner Losh /* The objects defined into this file should be considered experimental. 3487*0c16b537SWarner Losh * They are not labelled stable, as their prototype may change in the future. 3488*0c16b537SWarner Losh * You can use them for tests, provide feedback, or if you can endure risk of future changes. 3489*0c16b537SWarner Losh */ 3490*0c16b537SWarner Losh 3491*0c16b537SWarner Losh /* ************************************* 3492*0c16b537SWarner Losh * Includes 3493*0c16b537SWarner Losh ***************************************/ 3494*0c16b537SWarner Losh #include <stdlib.h> 3495*0c16b537SWarner Losh 3496*0c16b537SWarner Losh 3497*0c16b537SWarner Losh /** ************************************************ 3498*0c16b537SWarner Losh * Streaming decompression 3499*0c16b537SWarner Losh * 3500*0c16b537SWarner Losh * A ZBUFF_DCtx object is required to track streaming operation. 3501*0c16b537SWarner Losh * Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources. 3502*0c16b537SWarner Losh * Use ZBUFF_decompressInit() to start a new decompression operation. 3503*0c16b537SWarner Losh * ZBUFF_DCtx objects can be reused multiple times. 3504*0c16b537SWarner Losh * 3505*0c16b537SWarner Losh * Use ZBUFF_decompressContinue() repetitively to consume your input. 3506*0c16b537SWarner Losh * *srcSizePtr and *maxDstSizePtr can be any size. 3507*0c16b537SWarner Losh * The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr. 3508*0c16b537SWarner Losh * Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input. 3509*0c16b537SWarner Losh * The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst . 3510*0c16b537SWarner Losh * return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency) 3511*0c16b537SWarner Losh * or 0 when a frame is completely decoded 3512*0c16b537SWarner Losh * or an error code, which can be tested using ZBUFF_isError(). 3513*0c16b537SWarner Losh * 3514*0c16b537SWarner Losh * Hint : recommended buffer sizes (not compulsory) 3515*0c16b537SWarner Losh * output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded. 3516*0c16b537SWarner Losh * input : just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . 3517*0c16b537SWarner Losh * **************************************************/ 3518*0c16b537SWarner Losh 3519*0c16b537SWarner Losh typedef enum { ZBUFFds_init, ZBUFFds_readHeader, ZBUFFds_loadHeader, ZBUFFds_decodeHeader, 3520*0c16b537SWarner Losh ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFF_dStage; 3521*0c16b537SWarner Losh 3522*0c16b537SWarner Losh /* *** Resource management *** */ 3523*0c16b537SWarner Losh 3524*0c16b537SWarner Losh #define ZSTD_frameHeaderSize_max 5 /* too magical, should come from reference */ 3525*0c16b537SWarner Losh struct ZBUFFv04_DCtx_s { 3526*0c16b537SWarner Losh ZSTD_DCtx* zc; 3527*0c16b537SWarner Losh ZSTD_parameters params; 3528*0c16b537SWarner Losh char* inBuff; 3529*0c16b537SWarner Losh size_t inBuffSize; 3530*0c16b537SWarner Losh size_t inPos; 3531*0c16b537SWarner Losh char* outBuff; 3532*0c16b537SWarner Losh size_t outBuffSize; 3533*0c16b537SWarner Losh size_t outStart; 3534*0c16b537SWarner Losh size_t outEnd; 3535*0c16b537SWarner Losh size_t hPos; 3536*0c16b537SWarner Losh const char* dict; 3537*0c16b537SWarner Losh size_t dictSize; 3538*0c16b537SWarner Losh ZBUFF_dStage stage; 3539*0c16b537SWarner Losh unsigned char headerBuffer[ZSTD_frameHeaderSize_max]; 3540*0c16b537SWarner Losh }; /* typedef'd to ZBUFF_DCtx within "zstd_buffered.h" */ 3541*0c16b537SWarner Losh 3542*0c16b537SWarner Losh typedef ZBUFFv04_DCtx ZBUFF_DCtx; 3543*0c16b537SWarner Losh 3544*0c16b537SWarner Losh 3545*0c16b537SWarner Losh static ZBUFF_DCtx* ZBUFF_createDCtx(void) 3546*0c16b537SWarner Losh { 3547*0c16b537SWarner Losh ZBUFF_DCtx* zbc = (ZBUFF_DCtx*)malloc(sizeof(ZBUFF_DCtx)); 3548*0c16b537SWarner Losh if (zbc==NULL) return NULL; 3549*0c16b537SWarner Losh memset(zbc, 0, sizeof(*zbc)); 3550*0c16b537SWarner Losh zbc->zc = ZSTD_createDCtx(); 3551*0c16b537SWarner Losh zbc->stage = ZBUFFds_init; 3552*0c16b537SWarner Losh return zbc; 3553*0c16b537SWarner Losh } 3554*0c16b537SWarner Losh 3555*0c16b537SWarner Losh static size_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbc) 3556*0c16b537SWarner Losh { 3557*0c16b537SWarner Losh if (zbc==NULL) return 0; /* support free on null */ 3558*0c16b537SWarner Losh ZSTD_freeDCtx(zbc->zc); 3559*0c16b537SWarner Losh free(zbc->inBuff); 3560*0c16b537SWarner Losh free(zbc->outBuff); 3561*0c16b537SWarner Losh free(zbc); 3562*0c16b537SWarner Losh return 0; 3563*0c16b537SWarner Losh } 3564*0c16b537SWarner Losh 3565*0c16b537SWarner Losh 3566*0c16b537SWarner Losh /* *** Initialization *** */ 3567*0c16b537SWarner Losh 3568*0c16b537SWarner Losh static size_t ZBUFF_decompressInit(ZBUFF_DCtx* zbc) 3569*0c16b537SWarner Losh { 3570*0c16b537SWarner Losh zbc->stage = ZBUFFds_readHeader; 3571*0c16b537SWarner Losh zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = zbc->dictSize = 0; 3572*0c16b537SWarner Losh return ZSTD_resetDCtx(zbc->zc); 3573*0c16b537SWarner Losh } 3574*0c16b537SWarner Losh 3575*0c16b537SWarner Losh 3576*0c16b537SWarner Losh static size_t ZBUFF_decompressWithDictionary(ZBUFF_DCtx* zbc, const void* src, size_t srcSize) 3577*0c16b537SWarner Losh { 3578*0c16b537SWarner Losh zbc->dict = (const char*)src; 3579*0c16b537SWarner Losh zbc->dictSize = srcSize; 3580*0c16b537SWarner Losh return 0; 3581*0c16b537SWarner Losh } 3582*0c16b537SWarner Losh 3583*0c16b537SWarner Losh static size_t ZBUFF_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize) 3584*0c16b537SWarner Losh { 3585*0c16b537SWarner Losh size_t length = MIN(maxDstSize, srcSize); 3586*0c16b537SWarner Losh memcpy(dst, src, length); 3587*0c16b537SWarner Losh return length; 3588*0c16b537SWarner Losh } 3589*0c16b537SWarner Losh 3590*0c16b537SWarner Losh /* *** Decompression *** */ 3591*0c16b537SWarner Losh 3592*0c16b537SWarner Losh static size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr) 3593*0c16b537SWarner Losh { 3594*0c16b537SWarner Losh const char* const istart = (const char*)src; 3595*0c16b537SWarner Losh const char* ip = istart; 3596*0c16b537SWarner Losh const char* const iend = istart + *srcSizePtr; 3597*0c16b537SWarner Losh char* const ostart = (char*)dst; 3598*0c16b537SWarner Losh char* op = ostart; 3599*0c16b537SWarner Losh char* const oend = ostart + *maxDstSizePtr; 3600*0c16b537SWarner Losh U32 notDone = 1; 3601*0c16b537SWarner Losh 3602*0c16b537SWarner Losh while (notDone) 3603*0c16b537SWarner Losh { 3604*0c16b537SWarner Losh switch(zbc->stage) 3605*0c16b537SWarner Losh { 3606*0c16b537SWarner Losh 3607*0c16b537SWarner Losh case ZBUFFds_init : 3608*0c16b537SWarner Losh return ERROR(init_missing); 3609*0c16b537SWarner Losh 3610*0c16b537SWarner Losh case ZBUFFds_readHeader : 3611*0c16b537SWarner Losh /* read header from src */ 3612*0c16b537SWarner Losh { size_t const headerSize = ZSTD_getFrameParams(&(zbc->params), src, *srcSizePtr); 3613*0c16b537SWarner Losh if (ZSTD_isError(headerSize)) return headerSize; 3614*0c16b537SWarner Losh if (headerSize) { 3615*0c16b537SWarner Losh /* not enough input to decode header : tell how many bytes would be necessary */ 3616*0c16b537SWarner Losh memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr); 3617*0c16b537SWarner Losh zbc->hPos += *srcSizePtr; 3618*0c16b537SWarner Losh *maxDstSizePtr = 0; 3619*0c16b537SWarner Losh zbc->stage = ZBUFFds_loadHeader; 3620*0c16b537SWarner Losh return headerSize - zbc->hPos; 3621*0c16b537SWarner Losh } 3622*0c16b537SWarner Losh zbc->stage = ZBUFFds_decodeHeader; 3623*0c16b537SWarner Losh break; 3624*0c16b537SWarner Losh } 3625*0c16b537SWarner Losh 3626*0c16b537SWarner Losh case ZBUFFds_loadHeader: 3627*0c16b537SWarner Losh /* complete header from src */ 3628*0c16b537SWarner Losh { size_t headerSize = ZBUFF_limitCopy( 3629*0c16b537SWarner Losh zbc->headerBuffer + zbc->hPos, ZSTD_frameHeaderSize_max - zbc->hPos, 3630*0c16b537SWarner Losh src, *srcSizePtr); 3631*0c16b537SWarner Losh zbc->hPos += headerSize; 3632*0c16b537SWarner Losh ip += headerSize; 3633*0c16b537SWarner Losh headerSize = ZSTD_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos); 3634*0c16b537SWarner Losh if (ZSTD_isError(headerSize)) return headerSize; 3635*0c16b537SWarner Losh if (headerSize) { 3636*0c16b537SWarner Losh /* not enough input to decode header : tell how many bytes would be necessary */ 3637*0c16b537SWarner Losh *maxDstSizePtr = 0; 3638*0c16b537SWarner Losh return headerSize - zbc->hPos; 3639*0c16b537SWarner Losh } } 3640*0c16b537SWarner Losh /* intentional fallthrough */ 3641*0c16b537SWarner Losh 3642*0c16b537SWarner Losh case ZBUFFds_decodeHeader: 3643*0c16b537SWarner Losh /* apply header to create / resize buffers */ 3644*0c16b537SWarner Losh { size_t const neededOutSize = (size_t)1 << zbc->params.windowLog; 3645*0c16b537SWarner Losh size_t const neededInSize = BLOCKSIZE; /* a block is never > BLOCKSIZE */ 3646*0c16b537SWarner Losh if (zbc->inBuffSize < neededInSize) { 3647*0c16b537SWarner Losh free(zbc->inBuff); 3648*0c16b537SWarner Losh zbc->inBuffSize = neededInSize; 3649*0c16b537SWarner Losh zbc->inBuff = (char*)malloc(neededInSize); 3650*0c16b537SWarner Losh if (zbc->inBuff == NULL) return ERROR(memory_allocation); 3651*0c16b537SWarner Losh } 3652*0c16b537SWarner Losh if (zbc->outBuffSize < neededOutSize) { 3653*0c16b537SWarner Losh free(zbc->outBuff); 3654*0c16b537SWarner Losh zbc->outBuffSize = neededOutSize; 3655*0c16b537SWarner Losh zbc->outBuff = (char*)malloc(neededOutSize); 3656*0c16b537SWarner Losh if (zbc->outBuff == NULL) return ERROR(memory_allocation); 3657*0c16b537SWarner Losh } } 3658*0c16b537SWarner Losh if (zbc->dictSize) 3659*0c16b537SWarner Losh ZSTD_decompress_insertDictionary(zbc->zc, zbc->dict, zbc->dictSize); 3660*0c16b537SWarner Losh if (zbc->hPos) { 3661*0c16b537SWarner Losh /* some data already loaded into headerBuffer : transfer into inBuff */ 3662*0c16b537SWarner Losh memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos); 3663*0c16b537SWarner Losh zbc->inPos = zbc->hPos; 3664*0c16b537SWarner Losh zbc->hPos = 0; 3665*0c16b537SWarner Losh zbc->stage = ZBUFFds_load; 3666*0c16b537SWarner Losh break; 3667*0c16b537SWarner Losh } 3668*0c16b537SWarner Losh zbc->stage = ZBUFFds_read; 3669*0c16b537SWarner Losh /* fall-through */ 3670*0c16b537SWarner Losh case ZBUFFds_read: 3671*0c16b537SWarner Losh { 3672*0c16b537SWarner Losh size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc); 3673*0c16b537SWarner Losh if (neededInSize==0) /* end of frame */ 3674*0c16b537SWarner Losh { 3675*0c16b537SWarner Losh zbc->stage = ZBUFFds_init; 3676*0c16b537SWarner Losh notDone = 0; 3677*0c16b537SWarner Losh break; 3678*0c16b537SWarner Losh } 3679*0c16b537SWarner Losh if ((size_t)(iend-ip) >= neededInSize) 3680*0c16b537SWarner Losh { 3681*0c16b537SWarner Losh /* directly decode from src */ 3682*0c16b537SWarner Losh size_t decodedSize = ZSTD_decompressContinue(zbc->zc, 3683*0c16b537SWarner Losh zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart, 3684*0c16b537SWarner Losh ip, neededInSize); 3685*0c16b537SWarner Losh if (ZSTD_isError(decodedSize)) return decodedSize; 3686*0c16b537SWarner Losh ip += neededInSize; 3687*0c16b537SWarner Losh if (!decodedSize) break; /* this was just a header */ 3688*0c16b537SWarner Losh zbc->outEnd = zbc->outStart + decodedSize; 3689*0c16b537SWarner Losh zbc->stage = ZBUFFds_flush; 3690*0c16b537SWarner Losh break; 3691*0c16b537SWarner Losh } 3692*0c16b537SWarner Losh if (ip==iend) { notDone = 0; break; } /* no more input */ 3693*0c16b537SWarner Losh zbc->stage = ZBUFFds_load; 3694*0c16b537SWarner Losh } 3695*0c16b537SWarner Losh /* fall-through */ 3696*0c16b537SWarner Losh case ZBUFFds_load: 3697*0c16b537SWarner Losh { 3698*0c16b537SWarner Losh size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc); 3699*0c16b537SWarner Losh size_t toLoad = neededInSize - zbc->inPos; /* should always be <= remaining space within inBuff */ 3700*0c16b537SWarner Losh size_t loadedSize; 3701*0c16b537SWarner Losh if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected); /* should never happen */ 3702*0c16b537SWarner Losh loadedSize = ZBUFF_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip); 3703*0c16b537SWarner Losh ip += loadedSize; 3704*0c16b537SWarner Losh zbc->inPos += loadedSize; 3705*0c16b537SWarner Losh if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */ 3706*0c16b537SWarner Losh { 3707*0c16b537SWarner Losh size_t decodedSize = ZSTD_decompressContinue(zbc->zc, 3708*0c16b537SWarner Losh zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart, 3709*0c16b537SWarner Losh zbc->inBuff, neededInSize); 3710*0c16b537SWarner Losh if (ZSTD_isError(decodedSize)) return decodedSize; 3711*0c16b537SWarner Losh zbc->inPos = 0; /* input is consumed */ 3712*0c16b537SWarner Losh if (!decodedSize) { zbc->stage = ZBUFFds_read; break; } /* this was just a header */ 3713*0c16b537SWarner Losh zbc->outEnd = zbc->outStart + decodedSize; 3714*0c16b537SWarner Losh zbc->stage = ZBUFFds_flush; 3715*0c16b537SWarner Losh /* ZBUFFds_flush follows */ 3716*0c16b537SWarner Losh } 3717*0c16b537SWarner Losh } 3718*0c16b537SWarner Losh /* fall-through */ 3719*0c16b537SWarner Losh case ZBUFFds_flush: 3720*0c16b537SWarner Losh { 3721*0c16b537SWarner Losh size_t toFlushSize = zbc->outEnd - zbc->outStart; 3722*0c16b537SWarner Losh size_t flushedSize = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize); 3723*0c16b537SWarner Losh op += flushedSize; 3724*0c16b537SWarner Losh zbc->outStart += flushedSize; 3725*0c16b537SWarner Losh if (flushedSize == toFlushSize) 3726*0c16b537SWarner Losh { 3727*0c16b537SWarner Losh zbc->stage = ZBUFFds_read; 3728*0c16b537SWarner Losh if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize) 3729*0c16b537SWarner Losh zbc->outStart = zbc->outEnd = 0; 3730*0c16b537SWarner Losh break; 3731*0c16b537SWarner Losh } 3732*0c16b537SWarner Losh /* cannot flush everything */ 3733*0c16b537SWarner Losh notDone = 0; 3734*0c16b537SWarner Losh break; 3735*0c16b537SWarner Losh } 3736*0c16b537SWarner Losh default: return ERROR(GENERIC); /* impossible */ 3737*0c16b537SWarner Losh } 3738*0c16b537SWarner Losh } 3739*0c16b537SWarner Losh 3740*0c16b537SWarner Losh *srcSizePtr = ip-istart; 3741*0c16b537SWarner Losh *maxDstSizePtr = op-ostart; 3742*0c16b537SWarner Losh 3743*0c16b537SWarner Losh { 3744*0c16b537SWarner Losh size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbc->zc); 3745*0c16b537SWarner Losh if (nextSrcSizeHint > 3) nextSrcSizeHint+= 3; /* get the next block header while at it */ 3746*0c16b537SWarner Losh nextSrcSizeHint -= zbc->inPos; /* already loaded*/ 3747*0c16b537SWarner Losh return nextSrcSizeHint; 3748*0c16b537SWarner Losh } 3749*0c16b537SWarner Losh } 3750*0c16b537SWarner Losh 3751*0c16b537SWarner Losh 3752*0c16b537SWarner Losh /* ************************************* 3753*0c16b537SWarner Losh * Tool functions 3754*0c16b537SWarner Losh ***************************************/ 3755*0c16b537SWarner Losh unsigned ZBUFFv04_isError(size_t errorCode) { return ERR_isError(errorCode); } 3756*0c16b537SWarner Losh const char* ZBUFFv04_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } 3757*0c16b537SWarner Losh 3758*0c16b537SWarner Losh size_t ZBUFFv04_recommendedDInSize() { return BLOCKSIZE + 3; } 3759*0c16b537SWarner Losh size_t ZBUFFv04_recommendedDOutSize() { return BLOCKSIZE; } 3760*0c16b537SWarner Losh 3761*0c16b537SWarner Losh 3762*0c16b537SWarner Losh 3763*0c16b537SWarner Losh /*- ========================================================================= -*/ 3764*0c16b537SWarner Losh 3765*0c16b537SWarner Losh /* final wrapping stage */ 3766*0c16b537SWarner Losh 3767*0c16b537SWarner Losh size_t ZSTDv04_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) 3768*0c16b537SWarner Losh { 3769*0c16b537SWarner Losh return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0); 3770*0c16b537SWarner Losh } 3771*0c16b537SWarner Losh 3772*0c16b537SWarner Losh size_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize) 3773*0c16b537SWarner Losh { 3774*0c16b537SWarner Losh #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1) 3775*0c16b537SWarner Losh size_t regenSize; 3776*0c16b537SWarner Losh ZSTD_DCtx* dctx = ZSTD_createDCtx(); 3777*0c16b537SWarner Losh if (dctx==NULL) return ERROR(memory_allocation); 3778*0c16b537SWarner Losh regenSize = ZSTDv04_decompressDCtx(dctx, dst, maxDstSize, src, srcSize); 3779*0c16b537SWarner Losh ZSTD_freeDCtx(dctx); 3780*0c16b537SWarner Losh return regenSize; 3781*0c16b537SWarner Losh #else 3782*0c16b537SWarner Losh ZSTD_DCtx dctx; 3783*0c16b537SWarner Losh return ZSTDv04_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize); 3784*0c16b537SWarner Losh #endif 3785*0c16b537SWarner Losh } 3786*0c16b537SWarner Losh 3787*0c16b537SWarner Losh size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t srcSize) 3788*0c16b537SWarner Losh { 3789*0c16b537SWarner Losh return ZSTD_findFrameCompressedSize(src, srcSize); 3790*0c16b537SWarner Losh } 3791*0c16b537SWarner Losh 3792*0c16b537SWarner Losh size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); } 3793*0c16b537SWarner Losh 3794*0c16b537SWarner Losh size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx) 3795*0c16b537SWarner Losh { 3796*0c16b537SWarner Losh return ZSTD_nextSrcSizeToDecompress(dctx); 3797*0c16b537SWarner Losh } 3798*0c16b537SWarner Losh 3799*0c16b537SWarner Losh size_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) 3800*0c16b537SWarner Losh { 3801*0c16b537SWarner Losh return ZSTD_decompressContinue(dctx, dst, maxDstSize, src, srcSize); 3802*0c16b537SWarner Losh } 3803*0c16b537SWarner Losh 3804*0c16b537SWarner Losh 3805*0c16b537SWarner Losh 3806*0c16b537SWarner Losh ZBUFFv04_DCtx* ZBUFFv04_createDCtx(void) { return ZBUFF_createDCtx(); } 3807*0c16b537SWarner Losh size_t ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx) { return ZBUFF_freeDCtx(dctx); } 3808*0c16b537SWarner Losh 3809*0c16b537SWarner Losh size_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx) { return ZBUFF_decompressInit(dctx); } 3810*0c16b537SWarner Losh size_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* src, size_t srcSize) 3811*0c16b537SWarner Losh { return ZBUFF_decompressWithDictionary(dctx, src, srcSize); } 3812*0c16b537SWarner Losh 3813*0c16b537SWarner Losh size_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr) 3814*0c16b537SWarner Losh { 3815*0c16b537SWarner Losh return ZBUFF_decompressContinue(dctx, dst, maxDstSizePtr, src, srcSizePtr); 3816*0c16b537SWarner Losh } 3817*0c16b537SWarner Losh 3818*0c16b537SWarner Losh ZSTD_DCtx* ZSTDv04_createDCtx(void) { return ZSTD_createDCtx(); } 3819*0c16b537SWarner Losh size_t ZSTDv04_freeDCtx(ZSTD_DCtx* dctx) { return ZSTD_freeDCtx(dctx); } 3820*0c16b537SWarner Losh 3821*0c16b537SWarner Losh size_t ZSTDv04_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize) 3822*0c16b537SWarner Losh { 3823*0c16b537SWarner Losh return ZSTD_getFrameParams(params, src, srcSize); 3824*0c16b537SWarner Losh } 3825