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