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