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