extlz4 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -4
- data/bin/extlz4 +1 -1
- data/contrib/lz4/NEWS +36 -0
- data/contrib/lz4/README.md +11 -12
- data/contrib/lz4/build/README.md +55 -0
- data/contrib/lz4/build/VS2010/datagen/datagen.vcxproj +169 -0
- data/contrib/lz4/build/VS2010/frametest/frametest.vcxproj +176 -0
- data/contrib/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +180 -0
- data/contrib/lz4/build/VS2010/fullbench/fullbench.vcxproj +176 -0
- data/contrib/lz4/build/VS2010/fuzzer/fuzzer.vcxproj +173 -0
- data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc +51 -0
- data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj +179 -0
- data/contrib/lz4/build/VS2010/liblz4/liblz4.vcxproj +175 -0
- data/contrib/lz4/build/VS2010/lz4.sln +98 -0
- data/contrib/lz4/build/VS2010/lz4/lz4.rc +51 -0
- data/contrib/lz4/build/VS2010/lz4/lz4.vcxproj +189 -0
- data/contrib/lz4/build/VS2017/datagen/datagen.vcxproj +173 -0
- data/contrib/lz4/build/VS2017/frametest/frametest.vcxproj +180 -0
- data/contrib/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj +184 -0
- data/contrib/lz4/build/VS2017/fullbench/fullbench.vcxproj +180 -0
- data/contrib/lz4/build/VS2017/fuzzer/fuzzer.vcxproj +177 -0
- data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc +51 -0
- data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj +183 -0
- data/contrib/lz4/build/VS2017/liblz4/liblz4.vcxproj +179 -0
- data/contrib/lz4/build/VS2017/lz4.sln +103 -0
- data/contrib/lz4/build/VS2017/lz4/lz4.rc +51 -0
- data/contrib/lz4/build/VS2017/lz4/lz4.vcxproj +164 -0
- data/contrib/lz4/build/cmake/CMakeLists.txt +235 -0
- data/contrib/lz4/lib/README.md +27 -10
- data/contrib/lz4/lib/lz4.c +327 -230
- data/contrib/lz4/lib/lz4.h +80 -70
- data/contrib/lz4/lib/lz4frame.c +93 -54
- data/contrib/lz4/lib/lz4frame.h +22 -14
- data/contrib/lz4/lib/lz4hc.c +192 -115
- data/contrib/lz4/lib/lz4hc.h +15 -40
- data/contrib/lz4/ossfuzz/Makefile +12 -8
- data/contrib/lz4/ossfuzz/compress_frame_fuzzer.c +11 -5
- data/contrib/lz4/ossfuzz/compress_fuzzer.c +9 -2
- data/contrib/lz4/ossfuzz/compress_hc_fuzzer.c +10 -3
- data/contrib/lz4/ossfuzz/decompress_frame_fuzzer.c +11 -3
- data/contrib/lz4/ossfuzz/decompress_fuzzer.c +6 -2
- data/contrib/lz4/ossfuzz/fuzz_data_producer.c +77 -0
- data/contrib/lz4/ossfuzz/fuzz_data_producer.h +36 -0
- data/contrib/lz4/ossfuzz/round_trip_frame_fuzzer.c +8 -4
- data/contrib/lz4/ossfuzz/round_trip_fuzzer.c +9 -2
- data/contrib/lz4/ossfuzz/round_trip_hc_fuzzer.c +7 -2
- data/contrib/lz4/ossfuzz/travisoss.sh +6 -1
- data/contrib/lz4/tmp +0 -0
- data/contrib/lz4/tmpsparse +0 -0
- data/ext/extlz4.c +2 -0
- data/ext/extlz4.h +5 -0
- data/ext/hashargs.c +1 -1
- data/ext/hashargs.h +1 -1
- data/gemstub.rb +3 -14
- data/lib/extlz4.rb +0 -2
- data/lib/extlz4/oldstream.rb +1 -1
- metadata +40 -25
- data/lib/extlz4/version.rb +0 -3
data/contrib/lz4/lib/README.md
CHANGED
@@ -35,21 +35,22 @@ So it's necessary to include all `*.c` and `*.h` files present in `/lib`.
|
|
35
35
|
|
36
36
|
Definitions which are not guaranteed to remain stable in future versions,
|
37
37
|
are protected behind macros, such as `LZ4_STATIC_LINKING_ONLY`.
|
38
|
-
As the name implies, these definitions
|
38
|
+
As the name strongly implies, these definitions should only be invoked
|
39
39
|
in the context of static linking ***only***.
|
40
40
|
Otherwise, dependent application may fail on API or ABI break in the future.
|
41
|
-
The associated symbols are also not
|
41
|
+
The associated symbols are also not exposed by the dynamic library by default.
|
42
42
|
Should they be nonetheless needed, it's possible to force their publication
|
43
|
-
by using build
|
43
|
+
by using build macros `LZ4_PUBLISH_STATIC_FUNCTIONS`
|
44
|
+
and `LZ4F_PUBLISH_STATIC_FUNCTIONS`.
|
44
45
|
|
45
46
|
|
46
47
|
#### Build macros
|
47
48
|
|
48
|
-
The following build macro can be selected at compilation time :
|
49
|
+
The following build macro can be selected to adjust source code behavior at compilation time :
|
49
50
|
|
50
|
-
- `LZ4_FAST_DEC_LOOP` : this triggers
|
51
|
-
This
|
52
|
-
It's possible to enable or disable it manually, by passing `LZ4_FAST_DEC_LOOP=1` or `0` to the preprocessor.
|
51
|
+
- `LZ4_FAST_DEC_LOOP` : this triggers a speed optimized decompression loop, more powerful on modern cpus.
|
52
|
+
This loop works great on `x86`, `x64` and `aarch64` cpus, and is automatically enabled for them.
|
53
|
+
It's also possible to enable or disable it manually, by passing `LZ4_FAST_DEC_LOOP=1` or `0` to the preprocessor.
|
53
54
|
For example, with `gcc` : `-DLZ4_FAST_DEC_LOOP=1`,
|
54
55
|
and with `make` : `CPPFLAGS+=-DLZ4_FAST_DEC_LOOP=1 make lz4`.
|
55
56
|
|
@@ -65,8 +66,24 @@ The following build macro can be selected at compilation time :
|
|
65
66
|
Should this be a problem, it's generally possible to make the compiler ignore these warnings,
|
66
67
|
for example with `-Wno-deprecated-declarations` on `gcc`,
|
67
68
|
or `_CRT_SECURE_NO_WARNINGS` for Visual Studio.
|
68
|
-
|
69
|
-
before including the LZ4 header files.
|
69
|
+
This build macro offers another project-specific method
|
70
|
+
by defining `LZ4_DISABLE_DEPRECATE_WARNINGS` before including the LZ4 header files.
|
71
|
+
|
72
|
+
- `LZ4_USER_MEMORY_FUNCTIONS` : replace calls to <stdlib>'s `malloc`, `calloc` and `free`
|
73
|
+
by user-defined functions, which must be called `LZ4_malloc()`, `LZ4_calloc()` and `LZ4_free()`.
|
74
|
+
User functions must be available at link time.
|
75
|
+
|
76
|
+
- `LZ4_FORCE_SW_BITCOUNT` : by default, the compression algorithm tries to determine lengths
|
77
|
+
by using bitcount instructions, generally implemented as fast single instructions in many cpus.
|
78
|
+
In case the target cpus doesn't support it, or compiler intrinsic doesn't work, or feature bad performance,
|
79
|
+
it's possible to use an optimized software path instead.
|
80
|
+
This is achieved by setting this build macros .
|
81
|
+
In most cases, it's not expected to be necessary,
|
82
|
+
but it can be legitimately considered for less common platforms.
|
83
|
+
|
84
|
+
- `LZ4_ALIGN_TEST` : alignment test ensures that the memory area
|
85
|
+
passed as argument to become a compression state is suitably aligned.
|
86
|
+
This test can be disabled if it proves flaky, by setting this value to 0.
|
70
87
|
|
71
88
|
|
72
89
|
#### Amalgamation
|
@@ -102,7 +119,7 @@ The compiled executable will require LZ4 DLL which is available at `dll\liblz4.d
|
|
102
119
|
|
103
120
|
#### Miscellaneous
|
104
121
|
|
105
|
-
Other files present in the directory are not source code.
|
122
|
+
Other files present in the directory are not source code. They are :
|
106
123
|
|
107
124
|
- `LICENSE` : contains the BSD license text
|
108
125
|
- `Makefile` : `make` script to compile and install lz4 library (static and dynamic)
|
data/contrib/lz4/lib/lz4.c
CHANGED
@@ -45,10 +45,16 @@
|
|
45
45
|
#endif
|
46
46
|
|
47
47
|
/*
|
48
|
-
*
|
48
|
+
* LZ4_ACCELERATION_DEFAULT :
|
49
49
|
* Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
|
50
50
|
*/
|
51
|
-
#define
|
51
|
+
#define LZ4_ACCELERATION_DEFAULT 1
|
52
|
+
/*
|
53
|
+
* LZ4_ACCELERATION_MAX :
|
54
|
+
* Any "acceleration" value higher than this threshold
|
55
|
+
* get treated as LZ4_ACCELERATION_MAX instead (fix #876)
|
56
|
+
*/
|
57
|
+
#define LZ4_ACCELERATION_MAX 65537
|
52
58
|
|
53
59
|
|
54
60
|
/*-************************************
|
@@ -82,6 +88,7 @@
|
|
82
88
|
* Define this parameter if your target system or compiler does not support hardware bit count
|
83
89
|
*/
|
84
90
|
#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */
|
91
|
+
# undef LZ4_FORCE_SW_BITCOUNT /* avoid double def */
|
85
92
|
# define LZ4_FORCE_SW_BITCOUNT
|
86
93
|
#endif
|
87
94
|
|
@@ -114,10 +121,9 @@
|
|
114
121
|
/*-************************************
|
115
122
|
* Compiler Options
|
116
123
|
**************************************/
|
117
|
-
#
|
118
|
-
# include <intrin.h>
|
119
|
-
# pragma warning(disable : 4127)
|
120
|
-
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
|
124
|
+
#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */
|
125
|
+
# include <intrin.h> /* only present in VS2005+ */
|
126
|
+
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
121
127
|
#endif /* _MSC_VER */
|
122
128
|
|
123
129
|
#ifndef LZ4_FORCE_INLINE
|
@@ -136,7 +142,7 @@
|
|
136
142
|
# endif /* _MSC_VER */
|
137
143
|
#endif /* LZ4_FORCE_INLINE */
|
138
144
|
|
139
|
-
/*
|
145
|
+
/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE
|
140
146
|
* gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8,
|
141
147
|
* together with a simple 8-byte copy loop as a fall-back path.
|
142
148
|
* However, this optimization hurts the decompression speed by >30%,
|
@@ -151,11 +157,11 @@
|
|
151
157
|
* of LZ4_wildCopy8 does not affect the compression speed.
|
152
158
|
*/
|
153
159
|
#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__)
|
154
|
-
# define
|
155
|
-
#
|
160
|
+
# define LZ4_FORCE_O2 __attribute__((optimize("O2")))
|
161
|
+
# undef LZ4_FORCE_INLINE
|
162
|
+
# define LZ4_FORCE_INLINE static __inline __attribute__((optimize("O2"),always_inline))
|
156
163
|
#else
|
157
|
-
# define
|
158
|
-
# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static
|
164
|
+
# define LZ4_FORCE_O2
|
159
165
|
#endif
|
160
166
|
|
161
167
|
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
@@ -171,14 +177,33 @@
|
|
171
177
|
#define unlikely(expr) expect((expr) != 0, 0)
|
172
178
|
#endif
|
173
179
|
|
180
|
+
/* Should the alignment test prove unreliable, for some reason,
|
181
|
+
* it can be disabled by setting LZ4_ALIGN_TEST to 0 */
|
182
|
+
#ifndef LZ4_ALIGN_TEST /* can be externally provided */
|
183
|
+
# define LZ4_ALIGN_TEST 1
|
184
|
+
#endif
|
185
|
+
|
174
186
|
|
175
187
|
/*-************************************
|
176
188
|
* Memory routines
|
177
189
|
**************************************/
|
178
|
-
#
|
179
|
-
|
180
|
-
|
181
|
-
|
190
|
+
#ifdef LZ4_USER_MEMORY_FUNCTIONS
|
191
|
+
/* memory management functions can be customized by user project.
|
192
|
+
* Below functions must exist somewhere in the Project
|
193
|
+
* and be available at link time */
|
194
|
+
void* LZ4_malloc(size_t s);
|
195
|
+
void* LZ4_calloc(size_t n, size_t s);
|
196
|
+
void LZ4_free(void* p);
|
197
|
+
# define ALLOC(s) LZ4_malloc(s)
|
198
|
+
# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s)
|
199
|
+
# define FREEMEM(p) LZ4_free(p)
|
200
|
+
#else
|
201
|
+
# include <stdlib.h> /* malloc, calloc, free */
|
202
|
+
# define ALLOC(s) malloc(s)
|
203
|
+
# define ALLOC_AND_ZERO(s) calloc(1,s)
|
204
|
+
# define FREEMEM(p) free(p)
|
205
|
+
#endif
|
206
|
+
|
182
207
|
#include <string.h> /* memset, memcpy */
|
183
208
|
#define MEM_INIT(p,v,s) memset((p),(v),(s))
|
184
209
|
|
@@ -225,21 +250,27 @@ static const int LZ4_minLength = (MFLIMIT+1);
|
|
225
250
|
|
226
251
|
#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2)
|
227
252
|
# include <stdio.h>
|
228
|
-
static int g_debuglog_enable = 1;
|
229
|
-
# define DEBUGLOG(l, ...) {
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
253
|
+
static int g_debuglog_enable = 1;
|
254
|
+
# define DEBUGLOG(l, ...) { \
|
255
|
+
if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \
|
256
|
+
fprintf(stderr, __FILE__ ": "); \
|
257
|
+
fprintf(stderr, __VA_ARGS__); \
|
258
|
+
fprintf(stderr, " \n"); \
|
259
|
+
} }
|
235
260
|
#else
|
236
|
-
# define DEBUGLOG(l, ...)
|
261
|
+
# define DEBUGLOG(l, ...) {} /* disabled */
|
237
262
|
#endif
|
238
263
|
|
264
|
+
static int LZ4_isAligned(const void* ptr, size_t alignment)
|
265
|
+
{
|
266
|
+
return ((size_t)ptr & (alignment -1)) == 0;
|
267
|
+
}
|
268
|
+
|
239
269
|
|
240
270
|
/*-************************************
|
241
271
|
* Types
|
242
272
|
**************************************/
|
273
|
+
#include <limits.h>
|
243
274
|
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
244
275
|
# include <stdint.h>
|
245
276
|
typedef uint8_t BYTE;
|
@@ -249,6 +280,9 @@ static int g_debuglog_enable = 1;
|
|
249
280
|
typedef uint64_t U64;
|
250
281
|
typedef uintptr_t uptrval;
|
251
282
|
#else
|
283
|
+
# if UINT_MAX != 4294967295UL
|
284
|
+
# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4"
|
285
|
+
# endif
|
252
286
|
typedef unsigned char BYTE;
|
253
287
|
typedef unsigned short U16;
|
254
288
|
typedef unsigned int U32;
|
@@ -273,6 +307,21 @@ typedef enum {
|
|
273
307
|
/*-************************************
|
274
308
|
* Reading and writing into memory
|
275
309
|
**************************************/
|
310
|
+
|
311
|
+
/**
|
312
|
+
* LZ4 relies on memcpy with a constant size being inlined. In freestanding
|
313
|
+
* environments, the compiler can't assume the implementation of memcpy() is
|
314
|
+
* standard compliant, so it can't apply its specialized memcpy() inlining
|
315
|
+
* logic. When possible, use __builtin_memcpy() to tell the compiler to analyze
|
316
|
+
* memcpy() as if it were standard compliant, so it can inline it in freestanding
|
317
|
+
* environments. This is needed when decompressing the Linux Kernel, for example.
|
318
|
+
*/
|
319
|
+
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
320
|
+
#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)
|
321
|
+
#else
|
322
|
+
#define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)
|
323
|
+
#endif
|
324
|
+
|
276
325
|
static unsigned LZ4_isLittleEndian(void)
|
277
326
|
{
|
278
327
|
const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
|
@@ -307,27 +356,27 @@ static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = val
|
|
307
356
|
|
308
357
|
static U16 LZ4_read16(const void* memPtr)
|
309
358
|
{
|
310
|
-
U16 val;
|
359
|
+
U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
|
311
360
|
}
|
312
361
|
|
313
362
|
static U32 LZ4_read32(const void* memPtr)
|
314
363
|
{
|
315
|
-
U32 val;
|
364
|
+
U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
|
316
365
|
}
|
317
366
|
|
318
367
|
static reg_t LZ4_read_ARCH(const void* memPtr)
|
319
368
|
{
|
320
|
-
reg_t val;
|
369
|
+
reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
|
321
370
|
}
|
322
371
|
|
323
372
|
static void LZ4_write16(void* memPtr, U16 value)
|
324
373
|
{
|
325
|
-
|
374
|
+
LZ4_memcpy(memPtr, &value, sizeof(value));
|
326
375
|
}
|
327
376
|
|
328
377
|
static void LZ4_write32(void* memPtr, U32 value)
|
329
378
|
{
|
330
|
-
|
379
|
+
LZ4_memcpy(memPtr, &value, sizeof(value));
|
331
380
|
}
|
332
381
|
|
333
382
|
#endif /* LZ4_FORCE_MEMORY_ACCESS */
|
@@ -355,14 +404,14 @@ static void LZ4_writeLE16(void* memPtr, U16 value)
|
|
355
404
|
}
|
356
405
|
|
357
406
|
/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
|
358
|
-
|
407
|
+
LZ4_FORCE_INLINE
|
359
408
|
void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd)
|
360
409
|
{
|
361
410
|
BYTE* d = (BYTE*)dstPtr;
|
362
411
|
const BYTE* s = (const BYTE*)srcPtr;
|
363
412
|
BYTE* const e = (BYTE*)dstEnd;
|
364
413
|
|
365
|
-
do {
|
414
|
+
do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d<e);
|
366
415
|
}
|
367
416
|
|
368
417
|
static const unsigned inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
|
@@ -370,12 +419,12 @@ static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
|
|
370
419
|
|
371
420
|
|
372
421
|
#ifndef LZ4_FAST_DEC_LOOP
|
373
|
-
# if defined
|
422
|
+
# if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64
|
374
423
|
# define LZ4_FAST_DEC_LOOP 1
|
375
424
|
# elif defined(__aarch64__) && !defined(__clang__)
|
376
425
|
/* On aarch64, we disable this optimization for clang because on certain
|
377
|
-
* mobile chipsets
|
378
|
-
* refer to https://github.com/lz4/lz4/pull/707
|
426
|
+
* mobile chipsets, performance is reduced with clang. For information
|
427
|
+
* refer to https://github.com/lz4/lz4/pull/707 */
|
379
428
|
# define LZ4_FAST_DEC_LOOP 1
|
380
429
|
# else
|
381
430
|
# define LZ4_FAST_DEC_LOOP 0
|
@@ -384,20 +433,22 @@ static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
|
|
384
433
|
|
385
434
|
#if LZ4_FAST_DEC_LOOP
|
386
435
|
|
387
|
-
|
436
|
+
LZ4_FORCE_INLINE void
|
388
437
|
LZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)
|
389
438
|
{
|
439
|
+
assert(srcPtr + offset == dstPtr);
|
390
440
|
if (offset < 8) {
|
441
|
+
LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */
|
391
442
|
dstPtr[0] = srcPtr[0];
|
392
443
|
dstPtr[1] = srcPtr[1];
|
393
444
|
dstPtr[2] = srcPtr[2];
|
394
445
|
dstPtr[3] = srcPtr[3];
|
395
446
|
srcPtr += inc32table[offset];
|
396
|
-
|
447
|
+
LZ4_memcpy(dstPtr+4, srcPtr, 4);
|
397
448
|
srcPtr -= dec64table[offset];
|
398
449
|
dstPtr += 8;
|
399
450
|
} else {
|
400
|
-
|
451
|
+
LZ4_memcpy(dstPtr, srcPtr, 8);
|
401
452
|
dstPtr += 8;
|
402
453
|
srcPtr += 8;
|
403
454
|
}
|
@@ -408,49 +459,48 @@ LZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, con
|
|
408
459
|
/* customized variant of memcpy, which can overwrite up to 32 bytes beyond dstEnd
|
409
460
|
* this version copies two times 16 bytes (instead of one time 32 bytes)
|
410
461
|
* because it must be compatible with offsets >= 16. */
|
411
|
-
|
462
|
+
LZ4_FORCE_INLINE void
|
412
463
|
LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd)
|
413
464
|
{
|
414
465
|
BYTE* d = (BYTE*)dstPtr;
|
415
466
|
const BYTE* s = (const BYTE*)srcPtr;
|
416
467
|
BYTE* const e = (BYTE*)dstEnd;
|
417
468
|
|
418
|
-
do {
|
469
|
+
do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e);
|
419
470
|
}
|
420
471
|
|
421
472
|
/* LZ4_memcpy_using_offset() presumes :
|
422
473
|
* - dstEnd >= dstPtr + MINMATCH
|
423
474
|
* - there is at least 8 bytes available to write after dstEnd */
|
424
|
-
|
475
|
+
LZ4_FORCE_INLINE void
|
425
476
|
LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)
|
426
477
|
{
|
427
478
|
BYTE v[8];
|
428
479
|
|
429
480
|
assert(dstEnd >= dstPtr + MINMATCH);
|
430
|
-
LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */
|
431
481
|
|
432
482
|
switch(offset) {
|
433
483
|
case 1:
|
434
|
-
|
484
|
+
MEM_INIT(v, *srcPtr, 8);
|
435
485
|
break;
|
436
486
|
case 2:
|
437
|
-
|
438
|
-
|
439
|
-
|
487
|
+
LZ4_memcpy(v, srcPtr, 2);
|
488
|
+
LZ4_memcpy(&v[2], srcPtr, 2);
|
489
|
+
LZ4_memcpy(&v[4], v, 4);
|
440
490
|
break;
|
441
491
|
case 4:
|
442
|
-
|
443
|
-
|
492
|
+
LZ4_memcpy(v, srcPtr, 4);
|
493
|
+
LZ4_memcpy(&v[4], srcPtr, 4);
|
444
494
|
break;
|
445
495
|
default:
|
446
496
|
LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset);
|
447
497
|
return;
|
448
498
|
}
|
449
499
|
|
450
|
-
|
500
|
+
LZ4_memcpy(dstPtr, v, 8);
|
451
501
|
dstPtr += 8;
|
452
502
|
while (dstPtr < dstEnd) {
|
453
|
-
|
503
|
+
LZ4_memcpy(dstPtr, v, 8);
|
454
504
|
dstPtr += 8;
|
455
505
|
}
|
456
506
|
}
|
@@ -462,75 +512,92 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si
|
|
462
512
|
**************************************/
|
463
513
|
static unsigned LZ4_NbCommonBytes (reg_t val)
|
464
514
|
{
|
515
|
+
assert(val != 0);
|
465
516
|
if (LZ4_isLittleEndian()) {
|
466
|
-
if (sizeof(val)==8) {
|
467
|
-
# if defined(_MSC_VER) && defined(
|
517
|
+
if (sizeof(val) == 8) {
|
518
|
+
# if defined(_MSC_VER) && (_MSC_VER >= 1800) && defined(_M_AMD64) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
519
|
+
/* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */
|
520
|
+
return (unsigned)_tzcnt_u64(val) >> 3;
|
521
|
+
# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
468
522
|
unsigned long r = 0;
|
469
|
-
_BitScanForward64(
|
470
|
-
return (
|
471
|
-
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__
|
523
|
+
_BitScanForward64(&r, (U64)val);
|
524
|
+
return (unsigned)r >> 3;
|
525
|
+
# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
|
526
|
+
((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
|
527
|
+
!defined(LZ4_FORCE_SW_BITCOUNT)
|
472
528
|
return (unsigned)__builtin_ctzll((U64)val) >> 3;
|
473
529
|
# else
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
1, 3, 4, 4, 2, 5, 6, 7,
|
478
|
-
7, 0, 1, 2, 3, 3, 4, 6,
|
479
|
-
2, 6, 5, 5, 3, 4, 5, 6,
|
480
|
-
7, 1, 2, 4, 6, 4, 4, 5,
|
481
|
-
7, 2, 6, 5, 7, 6, 7, 7 };
|
482
|
-
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
530
|
+
const U64 m = 0x0101010101010101ULL;
|
531
|
+
val ^= val - 1;
|
532
|
+
return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56);
|
483
533
|
# endif
|
484
534
|
} else /* 32 bits */ {
|
485
|
-
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
535
|
+
# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
486
536
|
unsigned long r;
|
487
|
-
_BitScanForward(
|
488
|
-
return (
|
489
|
-
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__
|
537
|
+
_BitScanForward(&r, (U32)val);
|
538
|
+
return (unsigned)r >> 3;
|
539
|
+
# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
|
540
|
+
((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
|
541
|
+
!defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
490
542
|
return (unsigned)__builtin_ctz((U32)val) >> 3;
|
491
543
|
# else
|
492
|
-
|
493
|
-
|
494
|
-
3, 3, 1, 2, 2, 2, 2, 0,
|
495
|
-
3, 1, 2, 0, 1, 0, 1, 1 };
|
496
|
-
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
544
|
+
const U32 m = 0x01010101;
|
545
|
+
return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;
|
497
546
|
# endif
|
498
547
|
}
|
499
548
|
} else /* Big Endian CPU */ {
|
500
|
-
if (sizeof(val)==8) {
|
501
|
-
# if defined(
|
502
|
-
|
503
|
-
|
504
|
-
return (unsigned)(r>>3);
|
505
|
-
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
549
|
+
if (sizeof(val)==8) {
|
550
|
+
# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
|
551
|
+
((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
|
552
|
+
!defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
506
553
|
return (unsigned)__builtin_clzll((U64)val) >> 3;
|
507
554
|
# else
|
555
|
+
#if 1
|
556
|
+
/* this method is probably faster,
|
557
|
+
* but adds a 128 bytes lookup table */
|
558
|
+
static const unsigned char ctz7_tab[128] = {
|
559
|
+
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
560
|
+
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
561
|
+
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
562
|
+
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
563
|
+
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
564
|
+
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
565
|
+
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
566
|
+
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
567
|
+
};
|
568
|
+
U64 const mask = 0x0101010101010101ULL;
|
569
|
+
U64 const t = (((val >> 8) - mask) | val) & mask;
|
570
|
+
return ctz7_tab[(t * 0x0080402010080402ULL) >> 57];
|
571
|
+
#else
|
572
|
+
/* this method doesn't consume memory space like the previous one,
|
573
|
+
* but it contains several branches,
|
574
|
+
* that may end up slowing execution */
|
508
575
|
static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits.
|
509
|
-
|
510
|
-
|
576
|
+
Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.
|
577
|
+
Note that this code path is never triggered in 32-bits mode. */
|
511
578
|
unsigned r;
|
512
579
|
if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; }
|
513
580
|
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
514
581
|
r += (!val);
|
515
582
|
return r;
|
583
|
+
#endif
|
516
584
|
# endif
|
517
585
|
} else /* 32 bits */ {
|
518
|
-
# if defined(
|
519
|
-
|
520
|
-
|
521
|
-
return (unsigned)(r>>3);
|
522
|
-
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
586
|
+
# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
|
587
|
+
((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
|
588
|
+
!defined(LZ4_FORCE_SW_BITCOUNT)
|
523
589
|
return (unsigned)__builtin_clz((U32)val) >> 3;
|
524
590
|
# else
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
return
|
591
|
+
val >>= 8;
|
592
|
+
val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |
|
593
|
+
(val + 0x00FF0000)) >> 24;
|
594
|
+
return (unsigned)val ^ 3;
|
529
595
|
# endif
|
530
596
|
}
|
531
597
|
}
|
532
598
|
}
|
533
599
|
|
600
|
+
|
534
601
|
#define STEPSIZE sizeof(reg_t)
|
535
602
|
LZ4_FORCE_INLINE
|
536
603
|
unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
|
@@ -605,7 +672,7 @@ typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
|
|
605
672
|
int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
|
606
673
|
const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
|
607
674
|
int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
|
608
|
-
int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
|
675
|
+
int LZ4_sizeofState(void) { return LZ4_STREAMSIZE; }
|
609
676
|
|
610
677
|
|
611
678
|
/*-************************************
|
@@ -628,7 +695,7 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
|
628
695
|
/*-******************************
|
629
696
|
* Compression functions
|
630
697
|
********************************/
|
631
|
-
|
698
|
+
LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
|
632
699
|
{
|
633
700
|
if (tableType == byU16)
|
634
701
|
return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
|
@@ -636,7 +703,7 @@ static U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
|
|
636
703
|
return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
|
637
704
|
}
|
638
705
|
|
639
|
-
|
706
|
+
LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
|
640
707
|
{
|
641
708
|
const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
|
642
709
|
if (LZ4_isLittleEndian()) {
|
@@ -654,7 +721,7 @@ LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tab
|
|
654
721
|
return LZ4_hash4(LZ4_read32(p), tableType);
|
655
722
|
}
|
656
723
|
|
657
|
-
|
724
|
+
LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)
|
658
725
|
{
|
659
726
|
switch (tableType)
|
660
727
|
{
|
@@ -666,7 +733,7 @@ static void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)
|
|
666
733
|
}
|
667
734
|
}
|
668
735
|
|
669
|
-
|
736
|
+
LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)
|
670
737
|
{
|
671
738
|
switch (tableType)
|
672
739
|
{
|
@@ -678,7 +745,7 @@ static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t cons
|
|
678
745
|
}
|
679
746
|
}
|
680
747
|
|
681
|
-
|
748
|
+
LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h,
|
682
749
|
void* tableBase, tableType_t const tableType,
|
683
750
|
const BYTE* srcBase)
|
684
751
|
{
|
@@ -703,7 +770,7 @@ LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_
|
|
703
770
|
* Assumption 1 : only valid if tableType == byU32 or byU16.
|
704
771
|
* Assumption 2 : h is presumed valid (within limits of hash table)
|
705
772
|
*/
|
706
|
-
|
773
|
+
LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)
|
707
774
|
{
|
708
775
|
LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2);
|
709
776
|
if (tableType == byU32) {
|
@@ -739,22 +806,13 @@ LZ4_FORCE_INLINE void
|
|
739
806
|
LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
740
807
|
const int inputSize,
|
741
808
|
const tableType_t tableType) {
|
742
|
-
/* If compression failed during the previous step, then the context
|
743
|
-
* is marked as dirty, therefore, it has to be fully reset.
|
744
|
-
*/
|
745
|
-
if (cctx->dirty) {
|
746
|
-
DEBUGLOG(5, "LZ4_prepareTable: Full reset for %p", cctx);
|
747
|
-
MEM_INIT(cctx, 0, sizeof(LZ4_stream_t_internal));
|
748
|
-
return;
|
749
|
-
}
|
750
|
-
|
751
809
|
/* If the table hasn't been used, it's guaranteed to be zeroed out, and is
|
752
810
|
* therefore safe to use no matter what mode we're in. Otherwise, we figure
|
753
811
|
* out if it's safe to leave as is or whether it needs to be reset.
|
754
812
|
*/
|
755
|
-
if (cctx->tableType != clearedTable) {
|
813
|
+
if ((tableType_t)cctx->tableType != clearedTable) {
|
756
814
|
assert(inputSize >= 0);
|
757
|
-
if (cctx->tableType != tableType
|
815
|
+
if ((tableType_t)cctx->tableType != tableType
|
758
816
|
|| ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU)
|
759
817
|
|| ((tableType == byU32) && cctx->currentOffset > 1 GB)
|
760
818
|
|| tableType == byPtr
|
@@ -763,7 +821,7 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
|
763
821
|
DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx);
|
764
822
|
MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE);
|
765
823
|
cctx->currentOffset = 0;
|
766
|
-
cctx->tableType = clearedTable;
|
824
|
+
cctx->tableType = (U32)clearedTable;
|
767
825
|
} else {
|
768
826
|
DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)");
|
769
827
|
}
|
@@ -785,8 +843,12 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
|
785
843
|
}
|
786
844
|
|
787
845
|
/** LZ4_compress_generic() :
|
788
|
-
|
789
|
-
|
846
|
+
* inlined, to ensure branches are decided at compilation time.
|
847
|
+
* Presumed already validated at this stage:
|
848
|
+
* - source != NULL
|
849
|
+
* - inputSize > 0
|
850
|
+
*/
|
851
|
+
LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
|
790
852
|
LZ4_stream_t_internal* const cctx,
|
791
853
|
const char* const source,
|
792
854
|
char* const dest,
|
@@ -815,7 +877,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|
815
877
|
|
816
878
|
int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx);
|
817
879
|
U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */
|
818
|
-
const BYTE* const dictEnd = dictionary + dictSize;
|
880
|
+
const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary;
|
819
881
|
const BYTE* anchor = (const BYTE*) source;
|
820
882
|
const BYTE* const iend = ip + inputSize;
|
821
883
|
const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;
|
@@ -823,7 +885,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|
823
885
|
|
824
886
|
/* the dictCtx currentOffset is indexed on the start of the dictionary,
|
825
887
|
* while a dictionary in the current context precedes the currentOffset */
|
826
|
-
const BYTE* dictBase = (dictDirective == usingDictCtx) ?
|
888
|
+
const BYTE* dictBase = !dictionary ? NULL : (dictDirective == usingDictCtx) ?
|
827
889
|
dictionary + dictSize - dictCtx->currentOffset :
|
828
890
|
dictionary + dictSize - startIndex;
|
829
891
|
|
@@ -833,11 +895,11 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|
833
895
|
U32 offset = 0;
|
834
896
|
U32 forwardH;
|
835
897
|
|
836
|
-
DEBUGLOG(5, "
|
898
|
+
DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType);
|
899
|
+
assert(ip != NULL);
|
837
900
|
/* If init conditions are not met, we don't have to mark stream
|
838
901
|
* as having dirty context, since no action was taken yet */
|
839
902
|
if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */
|
840
|
-
if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported inputSize, too large (or negative) */
|
841
903
|
if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */
|
842
904
|
if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */
|
843
905
|
assert(acceleration >= 1);
|
@@ -854,7 +916,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|
854
916
|
cctx->dictSize += (U32)inputSize;
|
855
917
|
}
|
856
918
|
cctx->currentOffset += (U32)inputSize;
|
857
|
-
cctx->tableType = (
|
919
|
+
cctx->tableType = (U32)tableType;
|
858
920
|
|
859
921
|
if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
860
922
|
|
@@ -1147,13 +1209,14 @@ _last_literals:
|
|
1147
1209
|
if (outputDirective == fillOutput) {
|
1148
1210
|
/* adapt lastRun to fill 'dst' */
|
1149
1211
|
assert(olimit >= op);
|
1150
|
-
lastRun = (size_t)(olimit-op) - 1
|
1151
|
-
lastRun -= (lastRun+
|
1212
|
+
lastRun = (size_t)(olimit-op) - 1/*token*/;
|
1213
|
+
lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/
|
1152
1214
|
} else {
|
1153
1215
|
assert(outputDirective == limitedOutput);
|
1154
1216
|
return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
|
1155
1217
|
}
|
1156
1218
|
}
|
1219
|
+
DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun);
|
1157
1220
|
if (lastRun >= RUN_MASK) {
|
1158
1221
|
size_t accumulator = lastRun - RUN_MASK;
|
1159
1222
|
*op++ = RUN_MASK << ML_BITS;
|
@@ -1162,7 +1225,7 @@ _last_literals:
|
|
1162
1225
|
} else {
|
1163
1226
|
*op++ = (BYTE)(lastRun<<ML_BITS);
|
1164
1227
|
}
|
1165
|
-
|
1228
|
+
LZ4_memcpy(op, anchor, lastRun);
|
1166
1229
|
ip = anchor + lastRun;
|
1167
1230
|
op += lastRun;
|
1168
1231
|
}
|
@@ -1170,18 +1233,60 @@ _last_literals:
|
|
1170
1233
|
if (outputDirective == fillOutput) {
|
1171
1234
|
*inputConsumed = (int) (((const char*)ip)-source);
|
1172
1235
|
}
|
1173
|
-
DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, (int)(((char*)op) - dest));
|
1174
1236
|
result = (int)(((char*)op) - dest);
|
1175
1237
|
assert(result > 0);
|
1238
|
+
DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result);
|
1176
1239
|
return result;
|
1177
1240
|
}
|
1178
1241
|
|
1242
|
+
/** LZ4_compress_generic() :
|
1243
|
+
* inlined, to ensure branches are decided at compilation time;
|
1244
|
+
* takes care of src == (NULL, 0)
|
1245
|
+
* and forward the rest to LZ4_compress_generic_validated */
|
1246
|
+
LZ4_FORCE_INLINE int LZ4_compress_generic(
|
1247
|
+
LZ4_stream_t_internal* const cctx,
|
1248
|
+
const char* const src,
|
1249
|
+
char* const dst,
|
1250
|
+
const int srcSize,
|
1251
|
+
int *inputConsumed, /* only written when outputDirective == fillOutput */
|
1252
|
+
const int dstCapacity,
|
1253
|
+
const limitedOutput_directive outputDirective,
|
1254
|
+
const tableType_t tableType,
|
1255
|
+
const dict_directive dictDirective,
|
1256
|
+
const dictIssue_directive dictIssue,
|
1257
|
+
const int acceleration)
|
1258
|
+
{
|
1259
|
+
DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i",
|
1260
|
+
srcSize, dstCapacity);
|
1261
|
+
|
1262
|
+
if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */
|
1263
|
+
if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */
|
1264
|
+
if (outputDirective != notLimited && dstCapacity <= 0) return 0; /* no output, can't write anything */
|
1265
|
+
DEBUGLOG(5, "Generating an empty block");
|
1266
|
+
assert(outputDirective == notLimited || dstCapacity >= 1);
|
1267
|
+
assert(dst != NULL);
|
1268
|
+
dst[0] = 0;
|
1269
|
+
if (outputDirective == fillOutput) {
|
1270
|
+
assert (inputConsumed != NULL);
|
1271
|
+
*inputConsumed = 0;
|
1272
|
+
}
|
1273
|
+
return 1;
|
1274
|
+
}
|
1275
|
+
assert(src != NULL);
|
1276
|
+
|
1277
|
+
return LZ4_compress_generic_validated(cctx, src, dst, srcSize,
|
1278
|
+
inputConsumed, /* only written into if outputDirective == fillOutput */
|
1279
|
+
dstCapacity, outputDirective,
|
1280
|
+
tableType, dictDirective, dictIssue, acceleration);
|
1281
|
+
}
|
1282
|
+
|
1179
1283
|
|
1180
1284
|
int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
1181
1285
|
{
|
1182
1286
|
LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse;
|
1183
1287
|
assert(ctx != NULL);
|
1184
|
-
if (acceleration < 1) acceleration =
|
1288
|
+
if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
|
1289
|
+
if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
|
1185
1290
|
if (maxOutputSize >= LZ4_compressBound(inputSize)) {
|
1186
1291
|
if (inputSize < LZ4_64Klimit) {
|
1187
1292
|
return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
|
@@ -1211,7 +1316,8 @@ int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int
|
|
1211
1316
|
int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)
|
1212
1317
|
{
|
1213
1318
|
LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;
|
1214
|
-
if (acceleration < 1) acceleration =
|
1319
|
+
if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
|
1320
|
+
if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
|
1215
1321
|
|
1216
1322
|
if (dstCapacity >= LZ4_compressBound(srcSize)) {
|
1217
1323
|
if (srcSize < LZ4_64Klimit) {
|
@@ -1270,22 +1376,6 @@ int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputS
|
|
1270
1376
|
}
|
1271
1377
|
|
1272
1378
|
|
1273
|
-
/* hidden debug function */
|
1274
|
-
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
|
1275
|
-
int LZ4_compress_fast_force(const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)
|
1276
|
-
{
|
1277
|
-
LZ4_stream_t ctx;
|
1278
|
-
LZ4_initStream(&ctx, sizeof(ctx));
|
1279
|
-
|
1280
|
-
if (srcSize < LZ4_64Klimit) {
|
1281
|
-
return LZ4_compress_generic(&ctx.internal_donotuse, src, dst, srcSize, NULL, dstCapacity, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
1282
|
-
} else {
|
1283
|
-
tableType_t const addrMode = (sizeof(void*) > 4) ? byU32 : byPtr;
|
1284
|
-
return LZ4_compress_generic(&ctx.internal_donotuse, src, dst, srcSize, NULL, dstCapacity, limitedOutput, addrMode, noDict, noDictIssue, acceleration);
|
1285
|
-
}
|
1286
|
-
}
|
1287
|
-
|
1288
|
-
|
1289
1379
|
/* Note!: This function leaves the stream in an unclean/broken state!
|
1290
1380
|
* It is not safe to subsequently use the same state with a _fastReset() or
|
1291
1381
|
* _continue() call without resetting it. */
|
@@ -1340,27 +1430,23 @@ LZ4_stream_t* LZ4_createStream(void)
|
|
1340
1430
|
return lz4s;
|
1341
1431
|
}
|
1342
1432
|
|
1343
|
-
#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :
|
1344
|
-
it reports an aligment of 8-bytes,
|
1345
|
-
while actually aligning LZ4_stream_t on 4 bytes. */
|
1346
1433
|
static size_t LZ4_stream_t_alignment(void)
|
1347
1434
|
{
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1435
|
+
#if LZ4_ALIGN_TEST
|
1436
|
+
typedef struct { char c; LZ4_stream_t t; } t_a;
|
1437
|
+
return sizeof(t_a) - sizeof(LZ4_stream_t);
|
1438
|
+
#else
|
1439
|
+
return 1; /* effectively disabled */
|
1351
1440
|
#endif
|
1441
|
+
}
|
1352
1442
|
|
1353
1443
|
LZ4_stream_t* LZ4_initStream (void* buffer, size_t size)
|
1354
1444
|
{
|
1355
1445
|
DEBUGLOG(5, "LZ4_initStream");
|
1356
1446
|
if (buffer == NULL) { return NULL; }
|
1357
1447
|
if (size < sizeof(LZ4_stream_t)) { return NULL; }
|
1358
|
-
|
1359
|
-
|
1360
|
-
while actually aligning LZ4_stream_t on 4 bytes. */
|
1361
|
-
if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) { return NULL; } /* alignment check */
|
1362
|
-
#endif
|
1363
|
-
MEM_INIT(buffer, 0, sizeof(LZ4_stream_t));
|
1448
|
+
if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL;
|
1449
|
+
MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal));
|
1364
1450
|
return (LZ4_stream_t*)buffer;
|
1365
1451
|
}
|
1366
1452
|
|
@@ -1369,7 +1455,7 @@ LZ4_stream_t* LZ4_initStream (void* buffer, size_t size)
|
|
1369
1455
|
void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
|
1370
1456
|
{
|
1371
1457
|
DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream);
|
1372
|
-
MEM_INIT(LZ4_stream, 0, sizeof(
|
1458
|
+
MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal));
|
1373
1459
|
}
|
1374
1460
|
|
1375
1461
|
void LZ4_resetStream_fast(LZ4_stream_t* ctx) {
|
@@ -1418,7 +1504,7 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
|
|
1418
1504
|
base = dictEnd - dict->currentOffset;
|
1419
1505
|
dict->dictionary = p;
|
1420
1506
|
dict->dictSize = (U32)(dictEnd - p);
|
1421
|
-
dict->tableType = tableType;
|
1507
|
+
dict->tableType = (U32)tableType;
|
1422
1508
|
|
1423
1509
|
while (p <= dictEnd-HASH_UNIT) {
|
1424
1510
|
LZ4_putPosition(p, dict->hashTable, tableType, base);
|
@@ -1436,12 +1522,6 @@ void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dict
|
|
1436
1522
|
workingStream, dictionaryStream,
|
1437
1523
|
dictCtx != NULL ? dictCtx->dictSize : 0);
|
1438
1524
|
|
1439
|
-
/* Calling LZ4_resetStream_fast() here makes sure that changes will not be
|
1440
|
-
* erased by subsequent calls to LZ4_resetStream_fast() in case stream was
|
1441
|
-
* marked as having dirty context, e.g. requiring full reset.
|
1442
|
-
*/
|
1443
|
-
LZ4_resetStream_fast(workingStream);
|
1444
|
-
|
1445
1525
|
if (dictCtx != NULL) {
|
1446
1526
|
/* If the current offset is zero, we will never look in the
|
1447
1527
|
* external dictionary context, since there is no value a table
|
@@ -1493,9 +1573,9 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
|
|
1493
1573
|
|
1494
1574
|
DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i)", inputSize);
|
1495
1575
|
|
1496
|
-
if (streamPtr->dirty) { return 0; } /* Uninitialized structure detected */
|
1497
1576
|
LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */
|
1498
|
-
if (acceleration < 1) acceleration =
|
1577
|
+
if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
|
1578
|
+
if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
|
1499
1579
|
|
1500
1580
|
/* invalidate tiny dictionaries */
|
1501
1581
|
if ( (streamPtr->dictSize-1 < 4-1) /* intentional underflow */
|
@@ -1538,7 +1618,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
|
|
1538
1618
|
* cost to copy the dictionary's tables into the active context,
|
1539
1619
|
* so that the compression loop is only looking into one table.
|
1540
1620
|
*/
|
1541
|
-
|
1621
|
+
LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr));
|
1542
1622
|
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
|
1543
1623
|
} else {
|
1544
1624
|
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);
|
@@ -1593,7 +1673,9 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
|
1593
1673
|
if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
|
1594
1674
|
if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
|
1595
1675
|
|
1596
|
-
|
1676
|
+
if (safeBuffer == NULL) assert(dictSize == 0);
|
1677
|
+
if (dictSize > 0)
|
1678
|
+
memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
|
1597
1679
|
|
1598
1680
|
dict->dictionary = (const BYTE*)safeBuffer;
|
1599
1681
|
dict->dictSize = (U32)dictSize;
|
@@ -1623,25 +1705,27 @@ typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
|
|
1623
1705
|
*/
|
1624
1706
|
typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error;
|
1625
1707
|
LZ4_FORCE_INLINE unsigned
|
1626
|
-
read_variable_length(const BYTE**ip, const BYTE* lencheck,
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
s = **ip;
|
1636
|
-
(*ip)++;
|
1637
|
-
length += s;
|
1638
|
-
if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
|
1639
|
-
*error = loop_error;
|
1640
|
-
return length;
|
1708
|
+
read_variable_length(const BYTE**ip, const BYTE* lencheck,
|
1709
|
+
int loop_check, int initial_check,
|
1710
|
+
variable_length_error* error)
|
1711
|
+
{
|
1712
|
+
U32 length = 0;
|
1713
|
+
U32 s;
|
1714
|
+
if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
|
1715
|
+
*error = initial_error;
|
1716
|
+
return length;
|
1641
1717
|
}
|
1642
|
-
|
1718
|
+
do {
|
1719
|
+
s = **ip;
|
1720
|
+
(*ip)++;
|
1721
|
+
length += s;
|
1722
|
+
if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
|
1723
|
+
*error = loop_error;
|
1724
|
+
return length;
|
1725
|
+
}
|
1726
|
+
} while (s==255);
|
1643
1727
|
|
1644
|
-
|
1728
|
+
return length;
|
1645
1729
|
}
|
1646
1730
|
|
1647
1731
|
/*! LZ4_decompress_generic() :
|
@@ -1722,7 +1806,7 @@ LZ4_decompress_generic(
|
|
1722
1806
|
/* decode literal length */
|
1723
1807
|
if (length == RUN_MASK) {
|
1724
1808
|
variable_length_error error = ok;
|
1725
|
-
length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);
|
1809
|
+
length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
|
1726
1810
|
if (error == initial_error) { goto _output_error; }
|
1727
1811
|
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
|
1728
1812
|
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
|
@@ -1746,12 +1830,12 @@ LZ4_decompress_generic(
|
|
1746
1830
|
/* We don't need to check oend, since we check it once for each loop below */
|
1747
1831
|
if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; }
|
1748
1832
|
/* Literals can only be 14, but hope compilers optimize if we copy by a register size */
|
1749
|
-
|
1833
|
+
LZ4_memcpy(op, ip, 16);
|
1750
1834
|
} else { /* LZ4_decompress_fast() */
|
1751
1835
|
/* LZ4_decompress_fast() cannot copy more than 8 bytes at a time :
|
1752
1836
|
* it doesn't know input length, and relies on end-of-block properties */
|
1753
|
-
|
1754
|
-
if (length > 8) {
|
1837
|
+
LZ4_memcpy(op, ip, 8);
|
1838
|
+
if (length > 8) { LZ4_memcpy(op+8, ip+8, 8); }
|
1755
1839
|
}
|
1756
1840
|
ip += length; op = cpy;
|
1757
1841
|
}
|
@@ -1765,10 +1849,10 @@ LZ4_decompress_generic(
|
|
1765
1849
|
length = token & ML_MASK;
|
1766
1850
|
|
1767
1851
|
if (length == ML_MASK) {
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1852
|
+
variable_length_error error = ok;
|
1853
|
+
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
|
1854
|
+
length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);
|
1855
|
+
if (error != ok) { goto _output_error; }
|
1772
1856
|
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */
|
1773
1857
|
length += MINMATCH;
|
1774
1858
|
if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
|
@@ -1787,19 +1871,20 @@ LZ4_decompress_generic(
|
|
1787
1871
|
assert(match <= op);
|
1788
1872
|
assert(op + 18 <= oend);
|
1789
1873
|
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1874
|
+
LZ4_memcpy(op, match, 8);
|
1875
|
+
LZ4_memcpy(op+8, match+8, 8);
|
1876
|
+
LZ4_memcpy(op+16, match+16, 2);
|
1793
1877
|
op += length;
|
1794
1878
|
continue;
|
1795
1879
|
} } }
|
1796
1880
|
|
1797
|
-
if (
|
1881
|
+
if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
|
1798
1882
|
/* match starting within external dictionary */
|
1799
1883
|
if ((dict==usingExtDict) && (match < lowPrefix)) {
|
1800
1884
|
if (unlikely(op+length > oend-LASTLITERALS)) {
|
1801
1885
|
if (partialDecoding) {
|
1802
|
-
|
1886
|
+
DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd");
|
1887
|
+
length = MIN(length, (size_t)(oend-op));
|
1803
1888
|
} else {
|
1804
1889
|
goto _output_error; /* end-of-block condition violated */
|
1805
1890
|
} }
|
@@ -1812,14 +1897,14 @@ LZ4_decompress_generic(
|
|
1812
1897
|
/* match stretches into both external dictionary and current block */
|
1813
1898
|
size_t const copySize = (size_t)(lowPrefix - match);
|
1814
1899
|
size_t const restSize = length - copySize;
|
1815
|
-
|
1900
|
+
LZ4_memcpy(op, dictEnd - copySize, copySize);
|
1816
1901
|
op += copySize;
|
1817
1902
|
if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */
|
1818
1903
|
BYTE* const endOfMatch = op + restSize;
|
1819
1904
|
const BYTE* copyFrom = lowPrefix;
|
1820
1905
|
while (op < endOfMatch) { *op++ = *copyFrom++; }
|
1821
1906
|
} else {
|
1822
|
-
|
1907
|
+
LZ4_memcpy(op, lowPrefix, restSize);
|
1823
1908
|
op += restSize;
|
1824
1909
|
} }
|
1825
1910
|
continue;
|
@@ -1860,7 +1945,7 @@ LZ4_decompress_generic(
|
|
1860
1945
|
/* strictly "less than" on input, to re-enter the loop with at least one byte */
|
1861
1946
|
&& likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend)) ) {
|
1862
1947
|
/* Copy the literals */
|
1863
|
-
|
1948
|
+
LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
|
1864
1949
|
op += length; ip += length;
|
1865
1950
|
|
1866
1951
|
/* The second stage: prepare for match copying, decode full info.
|
@@ -1875,9 +1960,9 @@ LZ4_decompress_generic(
|
|
1875
1960
|
&& (offset >= 8)
|
1876
1961
|
&& (dict==withPrefix64k || match >= lowPrefix) ) {
|
1877
1962
|
/* Copy the match. */
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1963
|
+
LZ4_memcpy(op + 0, match + 0, 8);
|
1964
|
+
LZ4_memcpy(op + 8, match + 8, 8);
|
1965
|
+
LZ4_memcpy(op +16, match +16, 2);
|
1881
1966
|
op += length + MINMATCH;
|
1882
1967
|
/* Both stages worked, load the next token. */
|
1883
1968
|
continue;
|
@@ -1891,7 +1976,7 @@ LZ4_decompress_generic(
|
|
1891
1976
|
/* decode literal length */
|
1892
1977
|
if (length == RUN_MASK) {
|
1893
1978
|
variable_length_error error = ok;
|
1894
|
-
length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);
|
1979
|
+
length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
|
1895
1980
|
if (error == initial_error) { goto _output_error; }
|
1896
1981
|
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
|
1897
1982
|
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
|
@@ -1907,29 +1992,34 @@ LZ4_decompress_generic(
|
|
1907
1992
|
|| ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) )
|
1908
1993
|
{
|
1909
1994
|
/* We've either hit the input parsing restriction or the output parsing restriction.
|
1910
|
-
*
|
1911
|
-
*
|
1912
|
-
*
|
1995
|
+
* In the normal scenario, decoding a full block, it must be the last sequence,
|
1996
|
+
* otherwise it's an error (invalid input or dimensions).
|
1997
|
+
* In partialDecoding scenario, it's necessary to ensure there is no buffer overflow.
|
1913
1998
|
*/
|
1914
1999
|
if (partialDecoding) {
|
1915
2000
|
/* Since we are partial decoding we may be in this block because of the output parsing
|
1916
2001
|
* restriction, which is not valid since the output buffer is allowed to be undersized.
|
1917
2002
|
*/
|
1918
2003
|
assert(endOnInput);
|
1919
|
-
|
1920
|
-
|
2004
|
+
DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end")
|
2005
|
+
DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length);
|
2006
|
+
DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op));
|
2007
|
+
DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip));
|
2008
|
+
/* Finishing in the middle of a literals segment,
|
2009
|
+
* due to lack of input.
|
1921
2010
|
*/
|
1922
|
-
if (
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
2011
|
+
if (ip+length > iend) {
|
2012
|
+
length = (size_t)(iend-ip);
|
2013
|
+
cpy = op + length;
|
2014
|
+
}
|
2015
|
+
/* Finishing in the middle of a literals segment,
|
2016
|
+
* due to lack of output space.
|
1926
2017
|
*/
|
1927
2018
|
if (cpy > oend) {
|
1928
2019
|
cpy = oend;
|
1929
2020
|
assert(op<=oend);
|
1930
2021
|
length = (size_t)(oend-op);
|
1931
2022
|
}
|
1932
|
-
assert(ip+length <= iend);
|
1933
2023
|
} else {
|
1934
2024
|
/* We must be on the last sequence because of the parsing limitations so check
|
1935
2025
|
* that we exactly regenerate the original size (must be exact when !endOnInput).
|
@@ -1938,16 +2028,22 @@ LZ4_decompress_generic(
|
|
1938
2028
|
/* We must be on the last sequence (or invalid) because of the parsing limitations
|
1939
2029
|
* so check that we exactly consume the input and don't overrun the output buffer.
|
1940
2030
|
*/
|
1941
|
-
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) {
|
2031
|
+
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) {
|
2032
|
+
DEBUGLOG(6, "should have been last run of literals")
|
2033
|
+
DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend);
|
2034
|
+
DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);
|
2035
|
+
goto _output_error;
|
2036
|
+
}
|
1942
2037
|
}
|
1943
|
-
memmove(op, ip, length); /* supports overlapping memory regions
|
2038
|
+
memmove(op, ip, length); /* supports overlapping memory regions; only matters for in-place decompression scenarios */
|
1944
2039
|
ip += length;
|
1945
2040
|
op += length;
|
1946
|
-
/* Necessarily EOF when !partialDecoding.
|
1947
|
-
* it is EOF if we've either
|
1948
|
-
* the
|
2041
|
+
/* Necessarily EOF when !partialDecoding.
|
2042
|
+
* When partialDecoding, it is EOF if we've either
|
2043
|
+
* filled the output buffer or
|
2044
|
+
* can't proceed with reading an offset for following match.
|
1949
2045
|
*/
|
1950
|
-
if (!partialDecoding || (cpy == oend) || (ip
|
2046
|
+
if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) {
|
1951
2047
|
break;
|
1952
2048
|
}
|
1953
2049
|
} else {
|
@@ -1965,7 +2061,7 @@ LZ4_decompress_generic(
|
|
1965
2061
|
_copy_match:
|
1966
2062
|
if (length == ML_MASK) {
|
1967
2063
|
variable_length_error error = ok;
|
1968
|
-
length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);
|
2064
|
+
length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);
|
1969
2065
|
if (error != ok) goto _output_error;
|
1970
2066
|
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */
|
1971
2067
|
}
|
@@ -1990,14 +2086,14 @@ LZ4_decompress_generic(
|
|
1990
2086
|
/* match stretches into both external dictionary and current block */
|
1991
2087
|
size_t const copySize = (size_t)(lowPrefix - match);
|
1992
2088
|
size_t const restSize = length - copySize;
|
1993
|
-
|
2089
|
+
LZ4_memcpy(op, dictEnd - copySize, copySize);
|
1994
2090
|
op += copySize;
|
1995
2091
|
if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */
|
1996
2092
|
BYTE* const endOfMatch = op + restSize;
|
1997
2093
|
const BYTE* copyFrom = lowPrefix;
|
1998
2094
|
while (op < endOfMatch) *op++ = *copyFrom++;
|
1999
2095
|
} else {
|
2000
|
-
|
2096
|
+
LZ4_memcpy(op, lowPrefix, restSize);
|
2001
2097
|
op += restSize;
|
2002
2098
|
} }
|
2003
2099
|
continue;
|
@@ -2016,7 +2112,7 @@ LZ4_decompress_generic(
|
|
2016
2112
|
if (matchEnd > op) { /* overlap copy */
|
2017
2113
|
while (op < copyEnd) { *op++ = *match++; }
|
2018
2114
|
} else {
|
2019
|
-
|
2115
|
+
LZ4_memcpy(op, match, mlen);
|
2020
2116
|
}
|
2021
2117
|
op = copyEnd;
|
2022
2118
|
if (op == oend) { break; }
|
@@ -2030,10 +2126,10 @@ LZ4_decompress_generic(
|
|
2030
2126
|
op[2] = match[2];
|
2031
2127
|
op[3] = match[3];
|
2032
2128
|
match += inc32table[offset];
|
2033
|
-
|
2129
|
+
LZ4_memcpy(op+4, match, 4);
|
2034
2130
|
match -= dec64table[offset];
|
2035
2131
|
} else {
|
2036
|
-
|
2132
|
+
LZ4_memcpy(op, match, 8);
|
2037
2133
|
match += 8;
|
2038
2134
|
}
|
2039
2135
|
op += 8;
|
@@ -2048,7 +2144,7 @@ LZ4_decompress_generic(
|
|
2048
2144
|
}
|
2049
2145
|
while (op < cpy) { *op++ = *match++; }
|
2050
2146
|
} else {
|
2051
|
-
|
2147
|
+
LZ4_memcpy(op, match, 8);
|
2052
2148
|
if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); }
|
2053
2149
|
}
|
2054
2150
|
op = cpy; /* wildcopy correction */
|
@@ -2056,6 +2152,7 @@ LZ4_decompress_generic(
|
|
2056
2152
|
|
2057
2153
|
/* end of decoding */
|
2058
2154
|
if (endOnInput) {
|
2155
|
+
DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst));
|
2059
2156
|
return (int) (((char*)op)-dst); /* Nb of output bytes decoded */
|
2060
2157
|
} else {
|
2061
2158
|
return (int) (((const char*)ip)-src); /* Nb of input bytes read */
|
@@ -2070,7 +2167,7 @@ LZ4_decompress_generic(
|
|
2070
2167
|
|
2071
2168
|
/*===== Instantiate the API decoding functions. =====*/
|
2072
2169
|
|
2073
|
-
|
2170
|
+
LZ4_FORCE_O2
|
2074
2171
|
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
|
2075
2172
|
{
|
2076
2173
|
return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,
|
@@ -2078,7 +2175,7 @@ int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int
|
|
2078
2175
|
(BYTE*)dest, NULL, 0);
|
2079
2176
|
}
|
2080
2177
|
|
2081
|
-
|
2178
|
+
LZ4_FORCE_O2
|
2082
2179
|
int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity)
|
2083
2180
|
{
|
2084
2181
|
dstCapacity = MIN(targetOutputSize, dstCapacity);
|
@@ -2087,7 +2184,7 @@ int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize,
|
|
2087
2184
|
noDict, (BYTE*)dst, NULL, 0);
|
2088
2185
|
}
|
2089
2186
|
|
2090
|
-
|
2187
|
+
LZ4_FORCE_O2
|
2091
2188
|
int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
|
2092
2189
|
{
|
2093
2190
|
return LZ4_decompress_generic(source, dest, 0, originalSize,
|
@@ -2097,7 +2194,7 @@ int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
|
|
2097
2194
|
|
2098
2195
|
/*===== Instantiate a few more decoding cases, used more than once. =====*/
|
2099
2196
|
|
2100
|
-
|
2197
|
+
LZ4_FORCE_O2 /* Exported, an obsolete API function. */
|
2101
2198
|
int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
|
2102
2199
|
{
|
2103
2200
|
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
@@ -2113,7 +2210,7 @@ int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int origin
|
|
2113
2210
|
return LZ4_decompress_fast(source, dest, originalSize);
|
2114
2211
|
}
|
2115
2212
|
|
2116
|
-
|
2213
|
+
LZ4_FORCE_O2
|
2117
2214
|
static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize,
|
2118
2215
|
size_t prefixSize)
|
2119
2216
|
{
|
@@ -2122,7 +2219,7 @@ static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, i
|
|
2122
2219
|
(BYTE*)dest-prefixSize, NULL, 0);
|
2123
2220
|
}
|
2124
2221
|
|
2125
|
-
|
2222
|
+
LZ4_FORCE_O2
|
2126
2223
|
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
2127
2224
|
int compressedSize, int maxOutputSize,
|
2128
2225
|
const void* dictStart, size_t dictSize)
|
@@ -2132,7 +2229,7 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
|
2132
2229
|
(BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
2133
2230
|
}
|
2134
2231
|
|
2135
|
-
|
2232
|
+
LZ4_FORCE_O2
|
2136
2233
|
static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize,
|
2137
2234
|
const void* dictStart, size_t dictSize)
|
2138
2235
|
{
|
@@ -2221,7 +2318,7 @@ int LZ4_decoderRingBufferSize(int maxBlockSize)
|
|
2221
2318
|
If it's not possible, save the relevant part of decoded data into a safe buffer,
|
2222
2319
|
and indicate where it stands using LZ4_setStreamDecode()
|
2223
2320
|
*/
|
2224
|
-
|
2321
|
+
LZ4_FORCE_O2
|
2225
2322
|
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
|
2226
2323
|
{
|
2227
2324
|
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
|
@@ -2261,7 +2358,7 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
|
|
2261
2358
|
return result;
|
2262
2359
|
}
|
2263
2360
|
|
2264
|
-
|
2361
|
+
LZ4_FORCE_O2
|
2265
2362
|
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
|
2266
2363
|
{
|
2267
2364
|
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
|
@@ -2374,7 +2471,7 @@ int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize,
|
|
2374
2471
|
|
2375
2472
|
/* Obsolete Streaming functions */
|
2376
2473
|
|
2377
|
-
int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
|
2474
|
+
int LZ4_sizeofStreamState(void) { return LZ4_STREAMSIZE; }
|
2378
2475
|
|
2379
2476
|
int LZ4_resetStreamState(void* state, char* inputBuffer)
|
2380
2477
|
{
|