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