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