isomorfeus-ferret 0.17.2 → 0.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/isomorfeus_ferret_ext/benchmark.c +9 -20
- data/ext/isomorfeus_ferret_ext/benchmarks_all.h +1 -2
- data/ext/isomorfeus_ferret_ext/bm_hash.c +1 -2
- data/ext/isomorfeus_ferret_ext/brotli_dec_decode.c +4 -2
- data/ext/isomorfeus_ferret_ext/brotli_enc_encode.c +3 -2
- data/ext/isomorfeus_ferret_ext/frb_analysis.c +4 -5
- data/ext/isomorfeus_ferret_ext/frb_field_info.c +3 -4
- data/ext/isomorfeus_ferret_ext/frb_index.c +118 -125
- data/ext/isomorfeus_ferret_ext/frb_lazy_doc.c +14 -16
- data/ext/isomorfeus_ferret_ext/frb_search.c +31 -23
- data/ext/isomorfeus_ferret_ext/frb_store.c +27 -13
- data/ext/isomorfeus_ferret_ext/frb_utils.c +3 -6
- data/ext/isomorfeus_ferret_ext/frt_analysis.c +39 -46
- data/ext/isomorfeus_ferret_ext/frt_analysis.h +9 -9
- data/ext/isomorfeus_ferret_ext/frt_array.c +11 -22
- data/ext/isomorfeus_ferret_ext/frt_bitvector.h +3 -6
- data/ext/isomorfeus_ferret_ext/frt_doc_field.c +87 -0
- data/ext/isomorfeus_ferret_ext/frt_doc_field.h +26 -0
- data/ext/isomorfeus_ferret_ext/frt_document.c +4 -97
- data/ext/isomorfeus_ferret_ext/frt_document.h +2 -27
- data/ext/isomorfeus_ferret_ext/frt_except.c +8 -6
- data/ext/isomorfeus_ferret_ext/frt_except.h +1 -2
- data/ext/isomorfeus_ferret_ext/frt_field_index.c +13 -32
- data/ext/isomorfeus_ferret_ext/frt_field_index.h +0 -6
- data/ext/isomorfeus_ferret_ext/frt_field_info.c +69 -0
- data/ext/isomorfeus_ferret_ext/frt_field_info.h +49 -0
- data/ext/isomorfeus_ferret_ext/frt_field_infos.c +196 -0
- data/ext/isomorfeus_ferret_ext/frt_field_infos.h +35 -0
- data/ext/isomorfeus_ferret_ext/frt_global.c +10 -4
- data/ext/isomorfeus_ferret_ext/frt_global.h +11 -15
- data/ext/isomorfeus_ferret_ext/frt_hash.c +8 -8
- data/ext/isomorfeus_ferret_ext/frt_hash.h +1 -2
- data/ext/isomorfeus_ferret_ext/frt_hashset.c +20 -40
- data/ext/isomorfeus_ferret_ext/frt_hashset.h +1 -2
- data/ext/isomorfeus_ferret_ext/frt_helper.c +7 -15
- data/ext/isomorfeus_ferret_ext/frt_in_stream.c +35 -45
- data/ext/isomorfeus_ferret_ext/frt_in_stream.h +3 -2
- data/ext/isomorfeus_ferret_ext/frt_ind.c +20 -38
- data/ext/isomorfeus_ferret_ext/frt_index.c +292 -790
- data/ext/isomorfeus_ferret_ext/frt_index.h +1 -102
- data/ext/isomorfeus_ferret_ext/frt_lang.c +5 -10
- data/ext/isomorfeus_ferret_ext/frt_lazy_doc.c +3 -3
- data/ext/isomorfeus_ferret_ext/frt_lazy_doc.h +1 -1
- data/ext/isomorfeus_ferret_ext/frt_lazy_doc_field.c +18 -25
- data/ext/isomorfeus_ferret_ext/frt_lazy_doc_field.h +5 -5
- data/ext/isomorfeus_ferret_ext/frt_mdbx_store.c +102 -70
- data/ext/isomorfeus_ferret_ext/frt_mempool.c +8 -16
- data/ext/isomorfeus_ferret_ext/frt_multimapper.c +23 -46
- data/ext/isomorfeus_ferret_ext/frt_multimapper.h +4 -8
- data/ext/isomorfeus_ferret_ext/frt_out_stream.c +31 -43
- data/ext/isomorfeus_ferret_ext/frt_out_stream.h +2 -2
- data/ext/isomorfeus_ferret_ext/frt_posh.c +6 -819
- data/ext/isomorfeus_ferret_ext/frt_posh.h +0 -57
- data/ext/isomorfeus_ferret_ext/frt_priorityqueue.c +11 -22
- data/ext/isomorfeus_ferret_ext/frt_priorityqueue.h +1 -2
- data/ext/isomorfeus_ferret_ext/frt_q_boolean.c +85 -171
- data/ext/isomorfeus_ferret_ext/frt_q_match_all.c +8 -16
- data/ext/isomorfeus_ferret_ext/frt_q_multi_term.c +1 -2
- data/ext/isomorfeus_ferret_ext/frt_q_parser.c +49 -98
- data/ext/isomorfeus_ferret_ext/frt_q_phrase.c +52 -104
- data/ext/isomorfeus_ferret_ext/frt_q_range.c +6 -12
- data/ext/isomorfeus_ferret_ext/frt_q_span.c +113 -226
- data/ext/isomorfeus_ferret_ext/frt_q_wildcard.c +1 -2
- data/ext/isomorfeus_ferret_ext/frt_ram_store.c +134 -85
- data/ext/isomorfeus_ferret_ext/frt_search.c +82 -164
- data/ext/isomorfeus_ferret_ext/frt_similarity.c +11 -22
- data/ext/isomorfeus_ferret_ext/frt_similarity.h +1 -2
- data/ext/isomorfeus_ferret_ext/frt_store.c +13 -25
- data/ext/isomorfeus_ferret_ext/frt_store.h +86 -52
- data/ext/isomorfeus_ferret_ext/frt_term_vectors.c +8 -16
- data/ext/isomorfeus_ferret_ext/frt_win32.h +5 -10
- data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.c +12 -11
- data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.h +11 -13
- data/ext/isomorfeus_ferret_ext/lz4.c +422 -195
- data/ext/isomorfeus_ferret_ext/lz4.h +114 -46
- data/ext/isomorfeus_ferret_ext/lz4frame.c +421 -242
- data/ext/isomorfeus_ferret_ext/lz4frame.h +122 -53
- data/ext/isomorfeus_ferret_ext/lz4hc.c +127 -111
- data/ext/isomorfeus_ferret_ext/lz4hc.h +14 -14
- data/ext/isomorfeus_ferret_ext/lz4xxhash.h +1 -1
- data/ext/isomorfeus_ferret_ext/mdbx.c +3762 -2526
- data/ext/isomorfeus_ferret_ext/mdbx.h +115 -70
- data/ext/isomorfeus_ferret_ext/test.c +40 -87
- data/ext/isomorfeus_ferret_ext/test.h +3 -6
- data/ext/isomorfeus_ferret_ext/test_1710.c +11 -13
- data/ext/isomorfeus_ferret_ext/test_analysis.c +32 -64
- data/ext/isomorfeus_ferret_ext/test_array.c +6 -12
- data/ext/isomorfeus_ferret_ext/test_bitvector.c +12 -24
- data/ext/isomorfeus_ferret_ext/test_document.c +23 -33
- data/ext/isomorfeus_ferret_ext/test_except.c +10 -21
- data/ext/isomorfeus_ferret_ext/test_fields.c +62 -68
- data/ext/isomorfeus_ferret_ext/test_file_deleter.c +15 -23
- data/ext/isomorfeus_ferret_ext/test_filter.c +17 -27
- data/ext/isomorfeus_ferret_ext/test_global.c +14 -29
- data/ext/isomorfeus_ferret_ext/test_hash.c +19 -38
- data/ext/isomorfeus_ferret_ext/test_hashset.c +8 -16
- data/ext/isomorfeus_ferret_ext/test_helper.c +4 -8
- data/ext/isomorfeus_ferret_ext/test_highlighter.c +16 -28
- data/ext/isomorfeus_ferret_ext/test_index.c +277 -487
- data/ext/isomorfeus_ferret_ext/test_lang.c +7 -14
- data/ext/isomorfeus_ferret_ext/test_mdbx_store.c +2 -5
- data/ext/isomorfeus_ferret_ext/test_mempool.c +5 -10
- data/ext/isomorfeus_ferret_ext/test_multimapper.c +3 -6
- data/ext/isomorfeus_ferret_ext/test_priorityqueue.c +9 -18
- data/ext/isomorfeus_ferret_ext/test_q_const_score.c +4 -6
- data/ext/isomorfeus_ferret_ext/test_q_filtered.c +3 -4
- data/ext/isomorfeus_ferret_ext/test_q_fuzzy.c +9 -15
- data/ext/isomorfeus_ferret_ext/test_q_parser.c +8 -16
- data/ext/isomorfeus_ferret_ext/test_q_span.c +19 -35
- data/ext/isomorfeus_ferret_ext/test_ram_store.c +14 -13
- data/ext/isomorfeus_ferret_ext/test_search.c +60 -109
- data/ext/isomorfeus_ferret_ext/test_segments.c +8 -13
- data/ext/isomorfeus_ferret_ext/test_similarity.c +2 -4
- data/ext/isomorfeus_ferret_ext/test_sort.c +14 -24
- data/ext/isomorfeus_ferret_ext/test_store.c +96 -115
- data/ext/isomorfeus_ferret_ext/test_term.c +9 -15
- data/ext/isomorfeus_ferret_ext/test_term_vectors.c +9 -14
- data/ext/isomorfeus_ferret_ext/test_test.c +4 -8
- data/ext/isomorfeus_ferret_ext/test_threading.c +14 -20
- data/ext/isomorfeus_ferret_ext/testhelper.c +11 -21
- data/ext/isomorfeus_ferret_ext/testhelper.h +1 -1
- data/ext/isomorfeus_ferret_ext/tests_all.h +1 -2
- data/lib/isomorfeus/ferret/index/index.rb +1 -1
- data/lib/isomorfeus/ferret/version.rb +1 -1
- metadata +24 -4
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
LZ4 - Fast LZ compression algorithm
|
3
|
-
Copyright (C) 2011-
|
3
|
+
Copyright (C) 2011-2020, Yann Collet.
|
4
4
|
|
5
5
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
6
6
|
|
@@ -124,6 +124,7 @@
|
|
124
124
|
#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */
|
125
125
|
# include <intrin.h> /* only present in VS2005+ */
|
126
126
|
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
127
|
+
# pragma warning(disable : 6237) /* disable: C6237: conditional expression is always 0 */
|
127
128
|
#endif /* _MSC_VER */
|
128
129
|
|
129
130
|
#ifndef LZ4_FORCE_INLINE
|
@@ -187,7 +188,27 @@
|
|
187
188
|
/*-************************************
|
188
189
|
* Memory routines
|
189
190
|
**************************************/
|
190
|
-
|
191
|
+
|
192
|
+
/*! LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION :
|
193
|
+
* Disable relatively high-level LZ4/HC functions that use dynamic memory
|
194
|
+
* allocation functions (malloc(), calloc(), free()).
|
195
|
+
*
|
196
|
+
* Note that this is a compile-time switch. And since it disables
|
197
|
+
* public/stable LZ4 v1 API functions, we don't recommend using this
|
198
|
+
* symbol to generate a library for distribution.
|
199
|
+
*
|
200
|
+
* The following public functions are removed when this symbol is defined.
|
201
|
+
* - lz4 : LZ4_createStream, LZ4_freeStream,
|
202
|
+
* LZ4_createStreamDecode, LZ4_freeStreamDecode, LZ4_create (deprecated)
|
203
|
+
* - lz4hc : LZ4_createStreamHC, LZ4_freeStreamHC,
|
204
|
+
* LZ4_createHC (deprecated), LZ4_freeHC (deprecated)
|
205
|
+
* - lz4frame, lz4file : All LZ4F_* functions
|
206
|
+
*/
|
207
|
+
#if defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
208
|
+
# define ALLOC(s) lz4_error_memory_allocation_is_disabled
|
209
|
+
# define ALLOC_AND_ZERO(s) lz4_error_memory_allocation_is_disabled
|
210
|
+
# define FREEMEM(p) lz4_error_memory_allocation_is_disabled
|
211
|
+
#elif defined(LZ4_USER_MEMORY_FUNCTIONS)
|
191
212
|
/* memory management functions can be customized by user project.
|
192
213
|
* Below functions must exist somewhere in the Project
|
193
214
|
* and be available at link time */
|
@@ -204,8 +225,13 @@ void LZ4_free(void* p);
|
|
204
225
|
# define FREEMEM(p) free(p)
|
205
226
|
#endif
|
206
227
|
|
207
|
-
#
|
208
|
-
#
|
228
|
+
#if ! LZ4_FREESTANDING
|
229
|
+
# include <string.h> /* memset, memcpy */
|
230
|
+
#endif
|
231
|
+
#if !defined(LZ4_memset)
|
232
|
+
# define LZ4_memset(p,v,s) memset((p),(v),(s))
|
233
|
+
#endif
|
234
|
+
#define MEM_INIT(p,v,s) LZ4_memset((p),(v),(s))
|
209
235
|
|
210
236
|
|
211
237
|
/*-************************************
|
@@ -316,10 +342,20 @@ typedef enum {
|
|
316
342
|
* memcpy() as if it were standard compliant, so it can inline it in freestanding
|
317
343
|
* environments. This is needed when decompressing the Linux Kernel, for example.
|
318
344
|
*/
|
319
|
-
#if defined(
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
345
|
+
#if !defined(LZ4_memcpy)
|
346
|
+
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
347
|
+
# define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)
|
348
|
+
# else
|
349
|
+
# define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)
|
350
|
+
# endif
|
351
|
+
#endif
|
352
|
+
|
353
|
+
#if !defined(LZ4_memmove)
|
354
|
+
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
355
|
+
# define LZ4_memmove __builtin_memmove
|
356
|
+
# else
|
357
|
+
# define LZ4_memmove memmove
|
358
|
+
# endif
|
323
359
|
#endif
|
324
360
|
|
325
361
|
static unsigned LZ4_isLittleEndian(void)
|
@@ -343,14 +379,14 @@ static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
|
|
343
379
|
|
344
380
|
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
345
381
|
/* currently only defined for gcc and icc */
|
346
|
-
typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed))
|
382
|
+
typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) LZ4_unalign;
|
347
383
|
|
348
|
-
static U16 LZ4_read16(const void* ptr) { return ((const
|
349
|
-
static U32 LZ4_read32(const void* ptr) { return ((const
|
350
|
-
static reg_t LZ4_read_ARCH(const void* ptr) { return ((const
|
384
|
+
static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign*)ptr)->u16; }
|
385
|
+
static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign*)ptr)->u32; }
|
386
|
+
static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalign*)ptr)->uArch; }
|
351
387
|
|
352
|
-
static void LZ4_write16(void* memPtr, U16 value) { ((
|
353
|
-
static void LZ4_write32(void* memPtr, U32 value) { ((
|
388
|
+
static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign*)memPtr)->u16 = value; }
|
389
|
+
static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign*)memPtr)->u32 = value; }
|
354
390
|
|
355
391
|
#else /* safe and portable access using memcpy() */
|
356
392
|
|
@@ -421,10 +457,12 @@ static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
|
|
421
457
|
#ifndef LZ4_FAST_DEC_LOOP
|
422
458
|
# if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64
|
423
459
|
# define LZ4_FAST_DEC_LOOP 1
|
460
|
+
# elif defined(__aarch64__) && defined(__APPLE__)
|
461
|
+
# define LZ4_FAST_DEC_LOOP 1
|
424
462
|
# elif defined(__aarch64__) && !defined(__clang__)
|
425
|
-
/* On aarch64, we disable this optimization for clang because
|
426
|
-
* mobile chipsets, performance is reduced with clang. For
|
427
|
-
* refer to https://github.com/lz4/lz4/pull/707 */
|
463
|
+
/* On non-Apple aarch64, we disable this optimization for clang because
|
464
|
+
* on certain mobile chipsets, performance is reduced with clang. For
|
465
|
+
* more information refer to https://github.com/lz4/lz4/pull/707 */
|
428
466
|
# define LZ4_FAST_DEC_LOOP 1
|
429
467
|
# else
|
430
468
|
# define LZ4_FAST_DEC_LOOP 0
|
@@ -486,7 +524,14 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si
|
|
486
524
|
case 2:
|
487
525
|
LZ4_memcpy(v, srcPtr, 2);
|
488
526
|
LZ4_memcpy(&v[2], srcPtr, 2);
|
527
|
+
#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */
|
528
|
+
# pragma warning(push)
|
529
|
+
# pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */
|
530
|
+
#endif
|
489
531
|
LZ4_memcpy(&v[4], v, 4);
|
532
|
+
#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */
|
533
|
+
# pragma warning(pop)
|
534
|
+
#endif
|
490
535
|
break;
|
491
536
|
case 4:
|
492
537
|
LZ4_memcpy(v, srcPtr, 4);
|
@@ -515,9 +560,20 @@ static unsigned LZ4_NbCommonBytes (reg_t val)
|
|
515
560
|
assert(val != 0);
|
516
561
|
if (LZ4_isLittleEndian()) {
|
517
562
|
if (sizeof(val) == 8) {
|
518
|
-
# if defined(_MSC_VER) && (_MSC_VER >= 1800) && defined(_M_AMD64) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
563
|
+
# if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) && !defined(_M_ARM64EC)) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
564
|
+
/*-*************************************************************************************************
|
565
|
+
* ARM64EC is a Microsoft-designed ARM64 ABI compatible with AMD64 applications on ARM64 Windows 11.
|
566
|
+
* The ARM64EC ABI does not support AVX/AVX2/AVX512 instructions, nor their relevant intrinsics
|
567
|
+
* including _tzcnt_u64. Therefore, we need to neuter the _tzcnt_u64 code path for ARM64EC.
|
568
|
+
****************************************************************************************************/
|
569
|
+
# if defined(__clang__) && (__clang_major__ < 10)
|
570
|
+
/* Avoid undefined clang-cl intrinsics issue.
|
571
|
+
* See https://github.com/lz4/lz4/pull/1017 for details. */
|
572
|
+
return (unsigned)__builtin_ia32_tzcnt_u64(val) >> 3;
|
573
|
+
# else
|
519
574
|
/* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */
|
520
575
|
return (unsigned)_tzcnt_u64(val) >> 3;
|
576
|
+
# endif
|
521
577
|
# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
522
578
|
unsigned long r = 0;
|
523
579
|
_BitScanForward64(&r, (U64)val);
|
@@ -652,10 +708,10 @@ typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;
|
|
652
708
|
* - usingExtDict : Like withPrefix64k, but the preceding content is somewhere
|
653
709
|
* else in memory, starting at ctx->dictionary with length
|
654
710
|
* ctx->dictSize.
|
655
|
-
* - usingDictCtx :
|
656
|
-
*
|
657
|
-
* ctx->
|
658
|
-
*
|
711
|
+
* - usingDictCtx : Everything concerning the preceding content is
|
712
|
+
* in a separate context, pointed to by ctx->dictCtx.
|
713
|
+
* ctx->dictionary, ctx->dictSize, and table entries
|
714
|
+
* in the current context that refer to positions
|
659
715
|
* preceding the beginning of the current compression are
|
660
716
|
* ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx
|
661
717
|
* ->dictSize describe the location and size of the preceding
|
@@ -672,12 +728,12 @@ typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
|
|
672
728
|
int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
|
673
729
|
const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
|
674
730
|
int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
|
675
|
-
int LZ4_sizeofState(void) { return
|
731
|
+
int LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); }
|
676
732
|
|
677
733
|
|
678
|
-
|
679
|
-
* Internal Definitions used in Tests
|
680
|
-
|
734
|
+
/*-****************************************
|
735
|
+
* Internal Definitions, used only in Tests
|
736
|
+
*******************************************/
|
681
737
|
#if defined (__cplusplus)
|
682
738
|
extern "C" {
|
683
739
|
#endif
|
@@ -687,7 +743,9 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char*
|
|
687
743
|
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
688
744
|
int compressedSize, int maxOutputSize,
|
689
745
|
const void* dictStart, size_t dictSize);
|
690
|
-
|
746
|
+
int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,
|
747
|
+
int compressedSize, int targetOutputSize, int dstCapacity,
|
748
|
+
const void* dictStart, size_t dictSize);
|
691
749
|
#if defined (__cplusplus)
|
692
750
|
}
|
693
751
|
#endif
|
@@ -827,9 +885,10 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
|
827
885
|
}
|
828
886
|
}
|
829
887
|
|
830
|
-
/* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back,
|
831
|
-
* than compressing without a gap.
|
832
|
-
* currentOffset == 0 is faster still,
|
888
|
+
/* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back,
|
889
|
+
* is faster than compressing without a gap.
|
890
|
+
* However, compressing with currentOffset == 0 is faster still,
|
891
|
+
* so we preserve that case.
|
833
892
|
*/
|
834
893
|
if (cctx->currentOffset != 0 && tableType == byU32) {
|
835
894
|
DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset");
|
@@ -853,7 +912,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
|
|
853
912
|
const char* const source,
|
854
913
|
char* const dest,
|
855
914
|
const int inputSize,
|
856
|
-
int
|
915
|
+
int* inputConsumed, /* only written when outputDirective == fillOutput */
|
857
916
|
const int maxOutputSize,
|
858
917
|
const limitedOutput_directive outputDirective,
|
859
918
|
const tableType_t tableType,
|
@@ -885,7 +944,8 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
|
|
885
944
|
|
886
945
|
/* the dictCtx currentOffset is indexed on the start of the dictionary,
|
887
946
|
* while a dictionary in the current context precedes the currentOffset */
|
888
|
-
const BYTE* dictBase =
|
947
|
+
const BYTE* dictBase = (dictionary == NULL) ? NULL :
|
948
|
+
(dictDirective == usingDictCtx) ?
|
889
949
|
dictionary + dictSize - dictCtx->currentOffset :
|
890
950
|
dictionary + dictSize - startIndex;
|
891
951
|
|
@@ -981,10 +1041,11 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
|
|
981
1041
|
match = base + matchIndex;
|
982
1042
|
lowLimit = (const BYTE*)source;
|
983
1043
|
}
|
984
|
-
} else if (dictDirective==usingExtDict) {
|
1044
|
+
} else if (dictDirective == usingExtDict) {
|
985
1045
|
if (matchIndex < startIndex) {
|
986
1046
|
DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex);
|
987
1047
|
assert(startIndex - matchIndex >= MINMATCH);
|
1048
|
+
assert(dictBase);
|
988
1049
|
match = dictBase + matchIndex;
|
989
1050
|
lowLimit = dictionary;
|
990
1051
|
} else {
|
@@ -1048,7 +1109,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
|
|
1048
1109
|
_next_match:
|
1049
1110
|
/* at this stage, the following variables must be correctly set :
|
1050
1111
|
* - ip : at start of LZ operation
|
1051
|
-
* - match : at start of previous pattern
|
1112
|
+
* - match : at start of previous pattern occurrence; can be within current prefix, or within extDict
|
1052
1113
|
* - offset : if maybe_ext_memSegment==1 (constant)
|
1053
1114
|
* - lowLimit : must be == dictionary to mean "match is within extDict"; must be == source otherwise
|
1054
1115
|
* - token and *token : position to write 4-bits for match length; higher 4-bits for literal length supposed already written
|
@@ -1173,6 +1234,7 @@ _next_match:
|
|
1173
1234
|
}
|
1174
1235
|
} else if (dictDirective==usingExtDict) {
|
1175
1236
|
if (matchIndex < startIndex) {
|
1237
|
+
assert(dictBase);
|
1176
1238
|
match = dictBase + matchIndex;
|
1177
1239
|
lowLimit = dictionary; /* required for match length counter */
|
1178
1240
|
} else {
|
@@ -1355,7 +1417,7 @@ int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutp
|
|
1355
1417
|
{
|
1356
1418
|
int result;
|
1357
1419
|
#if (LZ4_HEAPMODE)
|
1358
|
-
LZ4_stream_t* ctxPtr = ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
|
1420
|
+
LZ4_stream_t* ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
|
1359
1421
|
if (ctxPtr == NULL) return 0;
|
1360
1422
|
#else
|
1361
1423
|
LZ4_stream_t ctx;
|
@@ -1420,15 +1482,17 @@ int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targe
|
|
1420
1482
|
* Streaming functions
|
1421
1483
|
********************************/
|
1422
1484
|
|
1485
|
+
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
1423
1486
|
LZ4_stream_t* LZ4_createStream(void)
|
1424
1487
|
{
|
1425
1488
|
LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
1426
|
-
LZ4_STATIC_ASSERT(
|
1489
|
+
LZ4_STATIC_ASSERT(sizeof(LZ4_stream_t) >= sizeof(LZ4_stream_t_internal));
|
1427
1490
|
DEBUGLOG(4, "LZ4_createStream %p", lz4s);
|
1428
1491
|
if (lz4s == NULL) return NULL;
|
1429
1492
|
LZ4_initStream(lz4s, sizeof(*lz4s));
|
1430
1493
|
return lz4s;
|
1431
1494
|
}
|
1495
|
+
#endif
|
1432
1496
|
|
1433
1497
|
static size_t LZ4_stream_t_alignment(void)
|
1434
1498
|
{
|
@@ -1462,6 +1526,7 @@ void LZ4_resetStream_fast(LZ4_stream_t* ctx) {
|
|
1462
1526
|
LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32);
|
1463
1527
|
}
|
1464
1528
|
|
1529
|
+
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
1465
1530
|
int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
|
1466
1531
|
{
|
1467
1532
|
if (!LZ4_stream) return 0; /* support free on NULL */
|
@@ -1469,6 +1534,7 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
|
|
1469
1534
|
FREEMEM(LZ4_stream);
|
1470
1535
|
return (0);
|
1471
1536
|
}
|
1537
|
+
#endif
|
1472
1538
|
|
1473
1539
|
|
1474
1540
|
#define HASH_UNIT sizeof(reg_t)
|
@@ -1514,8 +1580,9 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
|
|
1514
1580
|
return (int)dict->dictSize;
|
1515
1581
|
}
|
1516
1582
|
|
1517
|
-
void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream)
|
1518
|
-
|
1583
|
+
void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream)
|
1584
|
+
{
|
1585
|
+
const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL :
|
1519
1586
|
&(dictionaryStream->internal_donotuse);
|
1520
1587
|
|
1521
1588
|
DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)",
|
@@ -1568,36 +1635,40 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
|
|
1568
1635
|
int acceleration)
|
1569
1636
|
{
|
1570
1637
|
const tableType_t tableType = byU32;
|
1571
|
-
LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse;
|
1572
|
-
const
|
1638
|
+
LZ4_stream_t_internal* const streamPtr = &LZ4_stream->internal_donotuse;
|
1639
|
+
const char* dictEnd = streamPtr->dictSize ? (const char*)streamPtr->dictionary + streamPtr->dictSize : NULL;
|
1573
1640
|
|
1574
|
-
DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i)", inputSize);
|
1641
|
+
DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i, dictSize=%u)", inputSize, streamPtr->dictSize);
|
1575
1642
|
|
1576
|
-
LZ4_renormDictT(streamPtr, inputSize); /*
|
1643
|
+
LZ4_renormDictT(streamPtr, inputSize); /* fix index overflow */
|
1577
1644
|
if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;
|
1578
1645
|
if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;
|
1579
1646
|
|
1580
1647
|
/* invalidate tiny dictionaries */
|
1581
|
-
if ( (streamPtr->dictSize
|
1582
|
-
&& (dictEnd !=
|
1648
|
+
if ( (streamPtr->dictSize < 4) /* tiny dictionary : not enough for a hash */
|
1649
|
+
&& (dictEnd != source) /* prefix mode */
|
1650
|
+
&& (inputSize > 0) /* tolerance : don't lose history, in case next invocation would use prefix mode */
|
1651
|
+
&& (streamPtr->dictCtx == NULL) /* usingDictCtx */
|
1652
|
+
) {
|
1583
1653
|
DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary);
|
1654
|
+
/* remove dictionary existence from history, to employ faster prefix mode */
|
1584
1655
|
streamPtr->dictSize = 0;
|
1585
1656
|
streamPtr->dictionary = (const BYTE*)source;
|
1586
|
-
dictEnd =
|
1657
|
+
dictEnd = source;
|
1587
1658
|
}
|
1588
1659
|
|
1589
1660
|
/* Check overlapping input/dictionary space */
|
1590
|
-
{ const
|
1591
|
-
if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
|
1661
|
+
{ const char* const sourceEnd = source + inputSize;
|
1662
|
+
if ((sourceEnd > (const char*)streamPtr->dictionary) && (sourceEnd < dictEnd)) {
|
1592
1663
|
streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
|
1593
1664
|
if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
|
1594
1665
|
if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
|
1595
|
-
streamPtr->dictionary = dictEnd - streamPtr->dictSize;
|
1666
|
+
streamPtr->dictionary = (const BYTE*)dictEnd - streamPtr->dictSize;
|
1596
1667
|
}
|
1597
1668
|
}
|
1598
1669
|
|
1599
1670
|
/* prefix mode : source data follows dictionary */
|
1600
|
-
if (dictEnd ==
|
1671
|
+
if (dictEnd == source) {
|
1601
1672
|
if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
|
1602
1673
|
return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration);
|
1603
1674
|
else
|
@@ -1623,7 +1694,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
|
|
1623
1694
|
} else {
|
1624
1695
|
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);
|
1625
1696
|
}
|
1626
|
-
} else {
|
1697
|
+
} else { /* small data <= 4 KB */
|
1627
1698
|
if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {
|
1628
1699
|
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration);
|
1629
1700
|
} else {
|
@@ -1661,21 +1732,25 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char*
|
|
1661
1732
|
/*! LZ4_saveDict() :
|
1662
1733
|
* If previously compressed data block is not guaranteed to remain available at its memory location,
|
1663
1734
|
* save it into a safer place (char* safeBuffer).
|
1664
|
-
* Note :
|
1665
|
-
*
|
1666
|
-
*
|
1735
|
+
* Note : no need to call LZ4_loadDict() afterwards, dictionary is immediately usable,
|
1736
|
+
* one can therefore call LZ4_compress_fast_continue() right after.
|
1737
|
+
* @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
|
1667
1738
|
*/
|
1668
1739
|
int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
1669
1740
|
{
|
1670
1741
|
LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
|
1671
|
-
|
1742
|
+
|
1743
|
+
DEBUGLOG(5, "LZ4_saveDict : dictSize=%i, safeBuffer=%p", dictSize, safeBuffer);
|
1672
1744
|
|
1673
1745
|
if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
|
1674
1746
|
if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
|
1675
1747
|
|
1676
1748
|
if (safeBuffer == NULL) assert(dictSize == 0);
|
1677
|
-
if (dictSize > 0)
|
1678
|
-
|
1749
|
+
if (dictSize > 0) {
|
1750
|
+
const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
|
1751
|
+
assert(dict->dictionary);
|
1752
|
+
LZ4_memmove(safeBuffer, previousDictEnd - dictSize, (size_t)dictSize);
|
1753
|
+
}
|
1679
1754
|
|
1680
1755
|
dict->dictionary = (const BYTE*)safeBuffer;
|
1681
1756
|
dict->dictSize = (U32)dictSize;
|
@@ -1689,39 +1764,163 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
|
1689
1764
|
* Decompression functions
|
1690
1765
|
********************************/
|
1691
1766
|
|
1692
|
-
typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
|
1693
1767
|
typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
|
1694
1768
|
|
1695
1769
|
#undef MIN
|
1696
1770
|
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
|
1697
1771
|
|
1772
|
+
|
1773
|
+
/* variant for decompress_unsafe()
|
1774
|
+
* does not know end of input
|
1775
|
+
* presumes input is well formed
|
1776
|
+
* note : will consume at least one byte */
|
1777
|
+
size_t read_long_length_no_check(const BYTE** pp)
|
1778
|
+
{
|
1779
|
+
size_t b, l = 0;
|
1780
|
+
do { b = **pp; (*pp)++; l += b; } while (b==255);
|
1781
|
+
DEBUGLOG(6, "read_long_length_no_check: +length=%zu using %zu input bytes", l, l/255 + 1)
|
1782
|
+
return l;
|
1783
|
+
}
|
1784
|
+
|
1785
|
+
/* core decoder variant for LZ4_decompress_fast*()
|
1786
|
+
* for legacy support only : these entry points are deprecated.
|
1787
|
+
* - Presumes input is correctly formed (no defense vs malformed inputs)
|
1788
|
+
* - Does not know input size (presume input buffer is "large enough")
|
1789
|
+
* - Decompress a full block (only)
|
1790
|
+
* @return : nb of bytes read from input.
|
1791
|
+
* Note : this variant is not optimized for speed, just for maintenance.
|
1792
|
+
* the goal is to remove support of decompress_fast*() variants by v2.0
|
1793
|
+
**/
|
1794
|
+
LZ4_FORCE_INLINE int
|
1795
|
+
LZ4_decompress_unsafe_generic(
|
1796
|
+
const BYTE* const istart,
|
1797
|
+
BYTE* const ostart,
|
1798
|
+
int decompressedSize,
|
1799
|
+
|
1800
|
+
size_t prefixSize,
|
1801
|
+
const BYTE* const dictStart, /* only if dict==usingExtDict */
|
1802
|
+
const size_t dictSize /* note: =0 if dictStart==NULL */
|
1803
|
+
)
|
1804
|
+
{
|
1805
|
+
const BYTE* ip = istart;
|
1806
|
+
BYTE* op = (BYTE*)ostart;
|
1807
|
+
BYTE* const oend = ostart + decompressedSize;
|
1808
|
+
const BYTE* const prefixStart = ostart - prefixSize;
|
1809
|
+
|
1810
|
+
DEBUGLOG(5, "LZ4_decompress_unsafe_generic");
|
1811
|
+
if (dictStart == NULL) assert(dictSize == 0);
|
1812
|
+
|
1813
|
+
while (1) {
|
1814
|
+
/* start new sequence */
|
1815
|
+
unsigned token = *ip++;
|
1816
|
+
|
1817
|
+
/* literals */
|
1818
|
+
{ size_t ll = token >> ML_BITS;
|
1819
|
+
if (ll==15) {
|
1820
|
+
/* long literal length */
|
1821
|
+
ll += read_long_length_no_check(&ip);
|
1822
|
+
}
|
1823
|
+
if ((size_t)(oend-op) < ll) return -1; /* output buffer overflow */
|
1824
|
+
LZ4_memmove(op, ip, ll); /* support in-place decompression */
|
1825
|
+
op += ll;
|
1826
|
+
ip += ll;
|
1827
|
+
if ((size_t)(oend-op) < MFLIMIT) {
|
1828
|
+
if (op==oend) break; /* end of block */
|
1829
|
+
DEBUGLOG(5, "invalid: literals end at distance %zi from end of block", oend-op);
|
1830
|
+
/* incorrect end of block :
|
1831
|
+
* last match must start at least MFLIMIT==12 bytes before end of output block */
|
1832
|
+
return -1;
|
1833
|
+
} }
|
1834
|
+
|
1835
|
+
/* match */
|
1836
|
+
{ size_t ml = token & 15;
|
1837
|
+
size_t const offset = LZ4_readLE16(ip);
|
1838
|
+
ip+=2;
|
1839
|
+
|
1840
|
+
if (ml==15) {
|
1841
|
+
/* long literal length */
|
1842
|
+
ml += read_long_length_no_check(&ip);
|
1843
|
+
}
|
1844
|
+
ml += MINMATCH;
|
1845
|
+
|
1846
|
+
if ((size_t)(oend-op) < ml) return -1; /* output buffer overflow */
|
1847
|
+
|
1848
|
+
{ const BYTE* match = op - offset;
|
1849
|
+
|
1850
|
+
/* out of range */
|
1851
|
+
if (offset > (size_t)(op - prefixStart) + dictSize) {
|
1852
|
+
DEBUGLOG(6, "offset out of range");
|
1853
|
+
return -1;
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
/* check special case : extDict */
|
1857
|
+
if (offset > (size_t)(op - prefixStart)) {
|
1858
|
+
/* extDict scenario */
|
1859
|
+
const BYTE* const dictEnd = dictStart + dictSize;
|
1860
|
+
const BYTE* extMatch = dictEnd - (offset - (size_t)(op-prefixStart));
|
1861
|
+
size_t const extml = (size_t)(dictEnd - extMatch);
|
1862
|
+
if (extml > ml) {
|
1863
|
+
/* match entirely within extDict */
|
1864
|
+
LZ4_memmove(op, extMatch, ml);
|
1865
|
+
op += ml;
|
1866
|
+
ml = 0;
|
1867
|
+
} else {
|
1868
|
+
/* match split between extDict & prefix */
|
1869
|
+
LZ4_memmove(op, extMatch, extml);
|
1870
|
+
op += extml;
|
1871
|
+
ml -= extml;
|
1872
|
+
}
|
1873
|
+
match = prefixStart;
|
1874
|
+
}
|
1875
|
+
|
1876
|
+
/* match copy - slow variant, supporting overlap copy */
|
1877
|
+
{ size_t u;
|
1878
|
+
for (u=0; u<ml; u++) {
|
1879
|
+
op[u] = match[u];
|
1880
|
+
} } }
|
1881
|
+
op += ml;
|
1882
|
+
if ((size_t)(oend-op) < LASTLITERALS) {
|
1883
|
+
DEBUGLOG(5, "invalid: match ends at distance %zi from end of block", oend-op);
|
1884
|
+
/* incorrect end of block :
|
1885
|
+
* last match must stop at least LASTLITERALS==5 bytes before end of output block */
|
1886
|
+
return -1;
|
1887
|
+
}
|
1888
|
+
} /* match */
|
1889
|
+
} /* main loop */
|
1890
|
+
return (int)(ip - istart);
|
1891
|
+
}
|
1892
|
+
|
1893
|
+
|
1698
1894
|
/* Read the variable-length literal or match length.
|
1699
1895
|
*
|
1700
|
-
* ip
|
1701
|
-
*
|
1702
|
-
*
|
1703
|
-
*
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
LZ4_FORCE_INLINE
|
1708
|
-
read_variable_length(const BYTE**ip, const BYTE*
|
1709
|
-
int
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
return
|
1896
|
+
* @ip : input pointer
|
1897
|
+
* @ilimit : position after which if length is not decoded, the input is necessarily corrupted.
|
1898
|
+
* @initial_check - check ip >= ipmax before start of loop. Returns initial_error if so.
|
1899
|
+
* @error (output) - error code. Must be set to 0 before call.
|
1900
|
+
**/
|
1901
|
+
typedef size_t Rvl_t;
|
1902
|
+
static const Rvl_t rvl_error = (Rvl_t)(-1);
|
1903
|
+
LZ4_FORCE_INLINE Rvl_t
|
1904
|
+
read_variable_length(const BYTE** ip, const BYTE* ilimit,
|
1905
|
+
int initial_check)
|
1906
|
+
{
|
1907
|
+
Rvl_t s, length = 0;
|
1908
|
+
assert(ip != NULL);
|
1909
|
+
assert(*ip != NULL);
|
1910
|
+
assert(ilimit != NULL);
|
1911
|
+
if (initial_check && unlikely((*ip) >= ilimit)) { /* read limit reached */
|
1912
|
+
return rvl_error;
|
1717
1913
|
}
|
1718
1914
|
do {
|
1719
1915
|
s = **ip;
|
1720
1916
|
(*ip)++;
|
1721
1917
|
length += s;
|
1722
|
-
if (
|
1723
|
-
|
1724
|
-
|
1918
|
+
if (unlikely((*ip) > ilimit)) { /* read limit reached */
|
1919
|
+
return rvl_error;
|
1920
|
+
}
|
1921
|
+
/* accumulator overflow detection (32-bit mode only) */
|
1922
|
+
if ((sizeof(length)<8) && unlikely(length > ((Rvl_t)(-1)/2)) ) {
|
1923
|
+
return rvl_error;
|
1725
1924
|
}
|
1726
1925
|
} while (s==255);
|
1727
1926
|
|
@@ -1741,7 +1940,6 @@ LZ4_decompress_generic(
|
|
1741
1940
|
int srcSize,
|
1742
1941
|
int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */
|
1743
1942
|
|
1744
|
-
endCondition_directive endOnInput, /* endOnOutputSize, endOnInputSize */
|
1745
1943
|
earlyEnd_directive partialDecoding, /* full, partial */
|
1746
1944
|
dict_directive dict, /* noDict, withPrefix64k, usingExtDict */
|
1747
1945
|
const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */
|
@@ -1749,7 +1947,7 @@ LZ4_decompress_generic(
|
|
1749
1947
|
const size_t dictSize /* note : = 0 if noDict */
|
1750
1948
|
)
|
1751
1949
|
{
|
1752
|
-
if (src == NULL) { return -1; }
|
1950
|
+
if ((src == NULL) || (outputSize < 0)) { return -1; }
|
1753
1951
|
|
1754
1952
|
{ const BYTE* ip = (const BYTE*) src;
|
1755
1953
|
const BYTE* const iend = ip + srcSize;
|
@@ -1760,13 +1958,12 @@ LZ4_decompress_generic(
|
|
1760
1958
|
|
1761
1959
|
const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize;
|
1762
1960
|
|
1763
|
-
const int
|
1764
|
-
const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
|
1961
|
+
const int checkOffset = (dictSize < (int)(64 KB));
|
1765
1962
|
|
1766
1963
|
|
1767
1964
|
/* Set up the "end" pointers for the shortcut. */
|
1768
|
-
const BYTE* const shortiend = iend -
|
1769
|
-
const BYTE* const shortoend = oend -
|
1965
|
+
const BYTE* const shortiend = iend - 14 /*maxLL*/ - 2 /*offset*/;
|
1966
|
+
const BYTE* const shortoend = oend - 14 /*maxLL*/ - 18 /*maxML*/;
|
1770
1967
|
|
1771
1968
|
const BYTE* match;
|
1772
1969
|
size_t offset;
|
@@ -1778,83 +1975,70 @@ LZ4_decompress_generic(
|
|
1778
1975
|
|
1779
1976
|
/* Special cases */
|
1780
1977
|
assert(lowPrefix <= op);
|
1781
|
-
if (
|
1978
|
+
if (unlikely(outputSize==0)) {
|
1782
1979
|
/* Empty output buffer */
|
1783
1980
|
if (partialDecoding) return 0;
|
1784
1981
|
return ((srcSize==1) && (*ip==0)) ? 0 : -1;
|
1785
1982
|
}
|
1786
|
-
if (
|
1787
|
-
if ((endOnInput) && unlikely(srcSize==0)) { return -1; }
|
1983
|
+
if (unlikely(srcSize==0)) { return -1; }
|
1788
1984
|
|
1789
|
-
|
1985
|
+
/* LZ4_FAST_DEC_LOOP:
|
1986
|
+
* designed for modern OoO performance cpus,
|
1987
|
+
* where copying reliably 32-bytes is preferable to an unpredictable branch.
|
1988
|
+
* note : fast loop may show a regression for some client arm chips. */
|
1790
1989
|
#if LZ4_FAST_DEC_LOOP
|
1791
1990
|
if ((oend - op) < FASTLOOP_SAFE_DISTANCE) {
|
1792
1991
|
DEBUGLOG(6, "skip fast decode loop");
|
1793
1992
|
goto safe_decode;
|
1794
1993
|
}
|
1795
1994
|
|
1796
|
-
/* Fast loop : decode sequences as long as output <
|
1995
|
+
/* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */
|
1797
1996
|
while (1) {
|
1798
1997
|
/* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */
|
1799
1998
|
assert(oend - op >= FASTLOOP_SAFE_DISTANCE);
|
1800
|
-
|
1999
|
+
assert(ip < iend);
|
1801
2000
|
token = *ip++;
|
1802
2001
|
length = token >> ML_BITS; /* literal length */
|
1803
2002
|
|
1804
|
-
assert(!endOnInput || ip <= iend); /* ip < iend before the increment */
|
1805
|
-
|
1806
2003
|
/* decode literal length */
|
1807
2004
|
if (length == RUN_MASK) {
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
if (
|
1812
|
-
if (
|
2005
|
+
size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);
|
2006
|
+
if (addl == rvl_error) { goto _output_error; }
|
2007
|
+
length += addl;
|
2008
|
+
if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
|
2009
|
+
if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
|
1813
2010
|
|
1814
2011
|
/* copy literals */
|
1815
2012
|
cpy = op+length;
|
1816
2013
|
LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
|
1817
|
-
if (
|
1818
|
-
|
1819
|
-
LZ4_wildCopy32(op, ip, cpy);
|
1820
|
-
} else { /* LZ4_decompress_fast() */
|
1821
|
-
if (cpy>oend-8) { goto safe_literal_copy; }
|
1822
|
-
LZ4_wildCopy8(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time :
|
1823
|
-
* it doesn't know input length, and only relies on end-of-block properties */
|
1824
|
-
}
|
2014
|
+
if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }
|
2015
|
+
LZ4_wildCopy32(op, ip, cpy);
|
1825
2016
|
ip += length; op = cpy;
|
1826
2017
|
} else {
|
1827
2018
|
cpy = op+length;
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
LZ4_memcpy(op, ip, 16);
|
1834
|
-
} else { /* LZ4_decompress_fast() */
|
1835
|
-
/* LZ4_decompress_fast() cannot copy more than 8 bytes at a time :
|
1836
|
-
* it doesn't know input length, and relies on end-of-block properties */
|
1837
|
-
LZ4_memcpy(op, ip, 8);
|
1838
|
-
if (length > 8) { LZ4_memcpy(op+8, ip+8, 8); }
|
1839
|
-
}
|
2019
|
+
DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length);
|
2020
|
+
/* We don't need to check oend, since we check it once for each loop below */
|
2021
|
+
if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; }
|
2022
|
+
/* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */
|
2023
|
+
LZ4_memcpy(op, ip, 16);
|
1840
2024
|
ip += length; op = cpy;
|
1841
2025
|
}
|
1842
2026
|
|
1843
2027
|
/* get offset */
|
1844
2028
|
offset = LZ4_readLE16(ip); ip+=2;
|
1845
2029
|
match = op - offset;
|
1846
|
-
assert(match <= op);
|
2030
|
+
assert(match <= op); /* overflow check */
|
1847
2031
|
|
1848
2032
|
/* get matchlength */
|
1849
2033
|
length = token & ML_MASK;
|
1850
2034
|
|
1851
2035
|
if (length == ML_MASK) {
|
1852
|
-
|
1853
|
-
if (
|
1854
|
-
length +=
|
1855
|
-
if (error != ok) { goto _output_error; }
|
1856
|
-
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */
|
2036
|
+
size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);
|
2037
|
+
if (addl == rvl_error) { goto _output_error; }
|
2038
|
+
length += addl;
|
1857
2039
|
length += MINMATCH;
|
2040
|
+
if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */
|
2041
|
+
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
|
1858
2042
|
if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
|
1859
2043
|
goto safe_match_copy;
|
1860
2044
|
}
|
@@ -1864,7 +2048,7 @@ LZ4_decompress_generic(
|
|
1864
2048
|
goto safe_match_copy;
|
1865
2049
|
}
|
1866
2050
|
|
1867
|
-
/* Fastpath check:
|
2051
|
+
/* Fastpath check: skip LZ4_wildCopy32 when true */
|
1868
2052
|
if ((dict == withPrefix64k) || (match >= lowPrefix)) {
|
1869
2053
|
if (offset >= 8) {
|
1870
2054
|
assert(match >= lowPrefix);
|
@@ -1881,6 +2065,7 @@ LZ4_decompress_generic(
|
|
1881
2065
|
if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
|
1882
2066
|
/* match starting within external dictionary */
|
1883
2067
|
if ((dict==usingExtDict) && (match < lowPrefix)) {
|
2068
|
+
assert(dictEnd != NULL);
|
1884
2069
|
if (unlikely(op+length > oend-LASTLITERALS)) {
|
1885
2070
|
if (partialDecoding) {
|
1886
2071
|
DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd");
|
@@ -1891,7 +2076,7 @@ LZ4_decompress_generic(
|
|
1891
2076
|
|
1892
2077
|
if (length <= (size_t)(lowPrefix-match)) {
|
1893
2078
|
/* match fits entirely within external dictionary : just copy */
|
1894
|
-
|
2079
|
+
LZ4_memmove(op, dictEnd - (lowPrefix-match), length);
|
1895
2080
|
op += length;
|
1896
2081
|
} else {
|
1897
2082
|
/* match stretches into both external dictionary and current block */
|
@@ -1927,11 +2112,10 @@ LZ4_decompress_generic(
|
|
1927
2112
|
|
1928
2113
|
/* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */
|
1929
2114
|
while (1) {
|
2115
|
+
assert(ip < iend);
|
1930
2116
|
token = *ip++;
|
1931
2117
|
length = token >> ML_BITS; /* literal length */
|
1932
2118
|
|
1933
|
-
assert(!endOnInput || ip <= iend); /* ip < iend before the increment */
|
1934
|
-
|
1935
2119
|
/* A two-stage shortcut for the most common case:
|
1936
2120
|
* 1) If the literal length is 0..14, and there is enough space,
|
1937
2121
|
* enter the shortcut and copy 16 bytes on behalf of the literals
|
@@ -1941,11 +2125,11 @@ LZ4_decompress_generic(
|
|
1941
2125
|
* those 18 bytes earlier, upon entering the shortcut (in other words,
|
1942
2126
|
* there is a combined check for both stages).
|
1943
2127
|
*/
|
1944
|
-
if ( (
|
2128
|
+
if ( (length != RUN_MASK)
|
1945
2129
|
/* strictly "less than" on input, to re-enter the loop with at least one byte */
|
1946
|
-
&& likely((
|
2130
|
+
&& likely((ip < shortiend) & (op <= shortoend)) ) {
|
1947
2131
|
/* Copy the literals */
|
1948
|
-
LZ4_memcpy(op, ip,
|
2132
|
+
LZ4_memcpy(op, ip, 16);
|
1949
2133
|
op += length; ip += length;
|
1950
2134
|
|
1951
2135
|
/* The second stage: prepare for match copying, decode full info.
|
@@ -1975,11 +2159,11 @@ LZ4_decompress_generic(
|
|
1975
2159
|
|
1976
2160
|
/* decode literal length */
|
1977
2161
|
if (length == RUN_MASK) {
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
if (
|
1982
|
-
if (
|
2162
|
+
size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);
|
2163
|
+
if (addl == rvl_error) { goto _output_error; }
|
2164
|
+
length += addl;
|
2165
|
+
if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
|
2166
|
+
if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
|
1983
2167
|
}
|
1984
2168
|
|
1985
2169
|
/* copy literals */
|
@@ -1988,9 +2172,7 @@ LZ4_decompress_generic(
|
|
1988
2172
|
safe_literal_copy:
|
1989
2173
|
#endif
|
1990
2174
|
LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
|
1991
|
-
if (
|
1992
|
-
|| ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) )
|
1993
|
-
{
|
2175
|
+
if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) {
|
1994
2176
|
/* We've either hit the input parsing restriction or the output parsing restriction.
|
1995
2177
|
* In the normal scenario, decoding a full block, it must be the last sequence,
|
1996
2178
|
* otherwise it's an error (invalid input or dimensions).
|
@@ -2000,7 +2182,6 @@ LZ4_decompress_generic(
|
|
2000
2182
|
/* Since we are partial decoding we may be in this block because of the output parsing
|
2001
2183
|
* restriction, which is not valid since the output buffer is allowed to be undersized.
|
2002
2184
|
*/
|
2003
|
-
assert(endOnInput);
|
2004
2185
|
DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end")
|
2005
2186
|
DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length);
|
2006
2187
|
DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op));
|
@@ -2021,21 +2202,17 @@ LZ4_decompress_generic(
|
|
2021
2202
|
length = (size_t)(oend-op);
|
2022
2203
|
}
|
2023
2204
|
} else {
|
2024
|
-
/* We must be on the last sequence because of the parsing limitations so check
|
2025
|
-
* that we exactly regenerate the original size (must be exact when !endOnInput).
|
2026
|
-
*/
|
2027
|
-
if ((!endOnInput) && (cpy != oend)) { goto _output_error; }
|
2028
2205
|
/* We must be on the last sequence (or invalid) because of the parsing limitations
|
2029
2206
|
* so check that we exactly consume the input and don't overrun the output buffer.
|
2030
2207
|
*/
|
2031
|
-
if ((
|
2208
|
+
if ((ip+length != iend) || (cpy > oend)) {
|
2032
2209
|
DEBUGLOG(6, "should have been last run of literals")
|
2033
2210
|
DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend);
|
2034
2211
|
DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);
|
2035
2212
|
goto _output_error;
|
2036
2213
|
}
|
2037
2214
|
}
|
2038
|
-
|
2215
|
+
LZ4_memmove(op, ip, length); /* supports overlapping memory regions, for in-place decompression scenarios */
|
2039
2216
|
ip += length;
|
2040
2217
|
op += length;
|
2041
2218
|
/* Necessarily EOF when !partialDecoding.
|
@@ -2047,7 +2224,7 @@ LZ4_decompress_generic(
|
|
2047
2224
|
break;
|
2048
2225
|
}
|
2049
2226
|
} else {
|
2050
|
-
LZ4_wildCopy8(op, ip, cpy); /*
|
2227
|
+
LZ4_wildCopy8(op, ip, cpy); /* can overwrite up to 8 bytes beyond cpy */
|
2051
2228
|
ip += length; op = cpy;
|
2052
2229
|
}
|
2053
2230
|
|
@@ -2060,10 +2237,10 @@ LZ4_decompress_generic(
|
|
2060
2237
|
|
2061
2238
|
_copy_match:
|
2062
2239
|
if (length == ML_MASK) {
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
if (
|
2240
|
+
size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);
|
2241
|
+
if (addl == rvl_error) { goto _output_error; }
|
2242
|
+
length += addl;
|
2243
|
+
if (unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */
|
2067
2244
|
}
|
2068
2245
|
length += MINMATCH;
|
2069
2246
|
|
@@ -2073,6 +2250,7 @@ LZ4_decompress_generic(
|
|
2073
2250
|
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */
|
2074
2251
|
/* match starting within external dictionary */
|
2075
2252
|
if ((dict==usingExtDict) && (match < lowPrefix)) {
|
2253
|
+
assert(dictEnd != NULL);
|
2076
2254
|
if (unlikely(op+length > oend-LASTLITERALS)) {
|
2077
2255
|
if (partialDecoding) length = MIN(length, (size_t)(oend-op));
|
2078
2256
|
else goto _output_error; /* doesn't respect parsing restriction */
|
@@ -2080,7 +2258,7 @@ LZ4_decompress_generic(
|
|
2080
2258
|
|
2081
2259
|
if (length <= (size_t)(lowPrefix-match)) {
|
2082
2260
|
/* match fits entirely within external dictionary : just copy */
|
2083
|
-
|
2261
|
+
LZ4_memmove(op, dictEnd - (lowPrefix-match), length);
|
2084
2262
|
op += length;
|
2085
2263
|
} else {
|
2086
2264
|
/* match stretches into both external dictionary and current block */
|
@@ -2151,12 +2329,8 @@ LZ4_decompress_generic(
|
|
2151
2329
|
}
|
2152
2330
|
|
2153
2331
|
/* end of decoding */
|
2154
|
-
|
2155
|
-
|
2156
|
-
return (int) (((char*)op)-dst); /* Nb of output bytes decoded */
|
2157
|
-
} else {
|
2158
|
-
return (int) (((const char*)ip)-src); /* Nb of input bytes read */
|
2159
|
-
}
|
2332
|
+
DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst));
|
2333
|
+
return (int) (((char*)op)-dst); /* Nb of output bytes decoded */
|
2160
2334
|
|
2161
2335
|
/* Overflow error detected */
|
2162
2336
|
_output_error:
|
@@ -2171,7 +2345,7 @@ LZ4_FORCE_O2
|
|
2171
2345
|
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
|
2172
2346
|
{
|
2173
2347
|
return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,
|
2174
|
-
|
2348
|
+
decode_full_block, noDict,
|
2175
2349
|
(BYTE*)dest, NULL, 0);
|
2176
2350
|
}
|
2177
2351
|
|
@@ -2180,16 +2354,17 @@ int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize,
|
|
2180
2354
|
{
|
2181
2355
|
dstCapacity = MIN(targetOutputSize, dstCapacity);
|
2182
2356
|
return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
|
2183
|
-
|
2357
|
+
partial_decode,
|
2184
2358
|
noDict, (BYTE*)dst, NULL, 0);
|
2185
2359
|
}
|
2186
2360
|
|
2187
2361
|
LZ4_FORCE_O2
|
2188
2362
|
int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
|
2189
2363
|
{
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2364
|
+
DEBUGLOG(5, "LZ4_decompress_fast");
|
2365
|
+
return LZ4_decompress_unsafe_generic(
|
2366
|
+
(const BYTE*)source, (BYTE*)dest, originalSize,
|
2367
|
+
0, NULL, 0);
|
2193
2368
|
}
|
2194
2369
|
|
2195
2370
|
/*===== Instantiate a few more decoding cases, used more than once. =====*/
|
@@ -2198,16 +2373,25 @@ LZ4_FORCE_O2 /* Exported, an obsolete API function. */
|
|
2198
2373
|
int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
|
2199
2374
|
{
|
2200
2375
|
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
2201
|
-
|
2376
|
+
decode_full_block, withPrefix64k,
|
2377
|
+
(BYTE*)dest - 64 KB, NULL, 0);
|
2378
|
+
}
|
2379
|
+
|
2380
|
+
LZ4_FORCE_O2
|
2381
|
+
static int LZ4_decompress_safe_partial_withPrefix64k(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity)
|
2382
|
+
{
|
2383
|
+
dstCapacity = MIN(targetOutputSize, dstCapacity);
|
2384
|
+
return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
|
2385
|
+
partial_decode, withPrefix64k,
|
2202
2386
|
(BYTE*)dest - 64 KB, NULL, 0);
|
2203
2387
|
}
|
2204
2388
|
|
2205
2389
|
/* Another obsolete API function, paired with the previous one. */
|
2206
2390
|
int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
|
2207
2391
|
{
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2392
|
+
return LZ4_decompress_unsafe_generic(
|
2393
|
+
(const BYTE*)source, (BYTE*)dest, originalSize,
|
2394
|
+
64 KB, NULL, 0);
|
2211
2395
|
}
|
2212
2396
|
|
2213
2397
|
LZ4_FORCE_O2
|
@@ -2215,7 +2399,17 @@ static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, i
|
|
2215
2399
|
size_t prefixSize)
|
2216
2400
|
{
|
2217
2401
|
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
2218
|
-
|
2402
|
+
decode_full_block, noDict,
|
2403
|
+
(BYTE*)dest-prefixSize, NULL, 0);
|
2404
|
+
}
|
2405
|
+
|
2406
|
+
LZ4_FORCE_O2
|
2407
|
+
static int LZ4_decompress_safe_partial_withSmallPrefix(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity,
|
2408
|
+
size_t prefixSize)
|
2409
|
+
{
|
2410
|
+
dstCapacity = MIN(targetOutputSize, dstCapacity);
|
2411
|
+
return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
|
2412
|
+
partial_decode, noDict,
|
2219
2413
|
(BYTE*)dest-prefixSize, NULL, 0);
|
2220
2414
|
}
|
2221
2415
|
|
@@ -2225,7 +2419,18 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
|
2225
2419
|
const void* dictStart, size_t dictSize)
|
2226
2420
|
{
|
2227
2421
|
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
2228
|
-
|
2422
|
+
decode_full_block, usingExtDict,
|
2423
|
+
(BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
2424
|
+
}
|
2425
|
+
|
2426
|
+
LZ4_FORCE_O2
|
2427
|
+
int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,
|
2428
|
+
int compressedSize, int targetOutputSize, int dstCapacity,
|
2429
|
+
const void* dictStart, size_t dictSize)
|
2430
|
+
{
|
2431
|
+
dstCapacity = MIN(targetOutputSize, dstCapacity);
|
2432
|
+
return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,
|
2433
|
+
partial_decode, usingExtDict,
|
2229
2434
|
(BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
2230
2435
|
}
|
2231
2436
|
|
@@ -2233,9 +2438,9 @@ LZ4_FORCE_O2
|
|
2233
2438
|
static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize,
|
2234
2439
|
const void* dictStart, size_t dictSize)
|
2235
2440
|
{
|
2236
|
-
return
|
2237
|
-
|
2238
|
-
|
2441
|
+
return LZ4_decompress_unsafe_generic(
|
2442
|
+
(const BYTE*)source, (BYTE*)dest, originalSize,
|
2443
|
+
0, (const BYTE*)dictStart, dictSize);
|
2239
2444
|
}
|
2240
2445
|
|
2241
2446
|
/* The "double dictionary" mode, for use with e.g. ring buffers: the first part
|
@@ -2247,26 +2452,17 @@ int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compresse
|
|
2247
2452
|
size_t prefixSize, const void* dictStart, size_t dictSize)
|
2248
2453
|
{
|
2249
2454
|
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
2250
|
-
|
2251
|
-
(BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize);
|
2252
|
-
}
|
2253
|
-
|
2254
|
-
LZ4_FORCE_INLINE
|
2255
|
-
int LZ4_decompress_fast_doubleDict(const char* source, char* dest, int originalSize,
|
2256
|
-
size_t prefixSize, const void* dictStart, size_t dictSize)
|
2257
|
-
{
|
2258
|
-
return LZ4_decompress_generic(source, dest, 0, originalSize,
|
2259
|
-
endOnOutputSize, decode_full_block, usingExtDict,
|
2455
|
+
decode_full_block, usingExtDict,
|
2260
2456
|
(BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize);
|
2261
2457
|
}
|
2262
2458
|
|
2263
2459
|
/*===== streaming decompression functions =====*/
|
2264
2460
|
|
2461
|
+
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
2265
2462
|
LZ4_streamDecode_t* LZ4_createStreamDecode(void)
|
2266
2463
|
{
|
2267
|
-
|
2268
|
-
|
2269
|
-
return lz4s;
|
2464
|
+
LZ4_STATIC_ASSERT(sizeof(LZ4_streamDecode_t) >= sizeof(LZ4_streamDecode_t_internal));
|
2465
|
+
return (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));
|
2270
2466
|
}
|
2271
2467
|
|
2272
2468
|
int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
|
@@ -2275,6 +2471,7 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
|
|
2275
2471
|
FREEMEM(LZ4_stream);
|
2276
2472
|
return 0;
|
2277
2473
|
}
|
2474
|
+
#endif
|
2278
2475
|
|
2279
2476
|
/*! LZ4_setStreamDecode() :
|
2280
2477
|
* Use this function to instruct where to find the dictionary.
|
@@ -2285,8 +2482,13 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
|
|
2285
2482
|
int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
|
2286
2483
|
{
|
2287
2484
|
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
|
2288
|
-
lz4sd->prefixSize = (size_t)
|
2289
|
-
|
2485
|
+
lz4sd->prefixSize = (size_t)dictSize;
|
2486
|
+
if (dictSize) {
|
2487
|
+
assert(dictionary != NULL);
|
2488
|
+
lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
|
2489
|
+
} else {
|
2490
|
+
lz4sd->prefixEnd = (const BYTE*) dictionary;
|
2491
|
+
}
|
2290
2492
|
lz4sd->externalDict = NULL;
|
2291
2493
|
lz4sd->extDictSize = 0;
|
2292
2494
|
return 1;
|
@@ -2358,29 +2560,35 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
|
|
2358
2560
|
return result;
|
2359
2561
|
}
|
2360
2562
|
|
2361
|
-
LZ4_FORCE_O2
|
2362
|
-
|
2563
|
+
LZ4_FORCE_O2 int
|
2564
|
+
LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode,
|
2565
|
+
const char* source, char* dest, int originalSize)
|
2363
2566
|
{
|
2364
|
-
LZ4_streamDecode_t_internal* lz4sd =
|
2567
|
+
LZ4_streamDecode_t_internal* const lz4sd =
|
2568
|
+
(assert(LZ4_streamDecode!=NULL), &LZ4_streamDecode->internal_donotuse);
|
2365
2569
|
int result;
|
2570
|
+
|
2571
|
+
DEBUGLOG(5, "LZ4_decompress_fast_continue (toDecodeSize=%i)", originalSize);
|
2366
2572
|
assert(originalSize >= 0);
|
2367
2573
|
|
2368
2574
|
if (lz4sd->prefixSize == 0) {
|
2575
|
+
DEBUGLOG(5, "first invocation : no prefix nor extDict");
|
2369
2576
|
assert(lz4sd->extDictSize == 0);
|
2370
2577
|
result = LZ4_decompress_fast(source, dest, originalSize);
|
2371
2578
|
if (result <= 0) return result;
|
2372
2579
|
lz4sd->prefixSize = (size_t)originalSize;
|
2373
2580
|
lz4sd->prefixEnd = (BYTE*)dest + originalSize;
|
2374
2581
|
} else if (lz4sd->prefixEnd == (BYTE*)dest) {
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2582
|
+
DEBUGLOG(5, "continue using existing prefix");
|
2583
|
+
result = LZ4_decompress_unsafe_generic(
|
2584
|
+
(const BYTE*)source, (BYTE*)dest, originalSize,
|
2585
|
+
lz4sd->prefixSize,
|
2586
|
+
lz4sd->externalDict, lz4sd->extDictSize);
|
2380
2587
|
if (result <= 0) return result;
|
2381
2588
|
lz4sd->prefixSize += (size_t)originalSize;
|
2382
2589
|
lz4sd->prefixEnd += originalSize;
|
2383
2590
|
} else {
|
2591
|
+
DEBUGLOG(5, "prefix becomes extDict");
|
2384
2592
|
lz4sd->extDictSize = lz4sd->prefixSize;
|
2385
2593
|
lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
|
2386
2594
|
result = LZ4_decompress_fast_extDict(source, dest, originalSize,
|
@@ -2416,10 +2624,27 @@ int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressed
|
|
2416
2624
|
return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize);
|
2417
2625
|
}
|
2418
2626
|
|
2627
|
+
int LZ4_decompress_safe_partial_usingDict(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, const char* dictStart, int dictSize)
|
2628
|
+
{
|
2629
|
+
if (dictSize==0)
|
2630
|
+
return LZ4_decompress_safe_partial(source, dest, compressedSize, targetOutputSize, dstCapacity);
|
2631
|
+
if (dictStart+dictSize == dest) {
|
2632
|
+
if (dictSize >= 64 KB - 1) {
|
2633
|
+
return LZ4_decompress_safe_partial_withPrefix64k(source, dest, compressedSize, targetOutputSize, dstCapacity);
|
2634
|
+
}
|
2635
|
+
assert(dictSize >= 0);
|
2636
|
+
return LZ4_decompress_safe_partial_withSmallPrefix(source, dest, compressedSize, targetOutputSize, dstCapacity, (size_t)dictSize);
|
2637
|
+
}
|
2638
|
+
assert(dictSize >= 0);
|
2639
|
+
return LZ4_decompress_safe_partial_forceExtDict(source, dest, compressedSize, targetOutputSize, dstCapacity, dictStart, (size_t)dictSize);
|
2640
|
+
}
|
2641
|
+
|
2419
2642
|
int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
|
2420
2643
|
{
|
2421
2644
|
if (dictSize==0 || dictStart+dictSize == dest)
|
2422
|
-
return
|
2645
|
+
return LZ4_decompress_unsafe_generic(
|
2646
|
+
(const BYTE*)source, (BYTE*)dest, originalSize,
|
2647
|
+
(size_t)dictSize, NULL, 0);
|
2423
2648
|
assert(dictSize >= 0);
|
2424
2649
|
return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize);
|
2425
2650
|
}
|
@@ -2471,7 +2696,7 @@ int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize,
|
|
2471
2696
|
|
2472
2697
|
/* Obsolete Streaming functions */
|
2473
2698
|
|
2474
|
-
int LZ4_sizeofStreamState(void) { return
|
2699
|
+
int LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); }
|
2475
2700
|
|
2476
2701
|
int LZ4_resetStreamState(void* state, char* inputBuffer)
|
2477
2702
|
{
|
@@ -2480,11 +2705,13 @@ int LZ4_resetStreamState(void* state, char* inputBuffer)
|
|
2480
2705
|
return 0;
|
2481
2706
|
}
|
2482
2707
|
|
2708
|
+
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
2483
2709
|
void* LZ4_create (char* inputBuffer)
|
2484
2710
|
{
|
2485
2711
|
(void)inputBuffer;
|
2486
2712
|
return LZ4_createStream();
|
2487
2713
|
}
|
2714
|
+
#endif
|
2488
2715
|
|
2489
2716
|
char* LZ4_slideInputBuffer (void* state)
|
2490
2717
|
{
|