extzstd 0.0.3.CONCEPT-x86-mingw32 → 0.1-x86-mingw32

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