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