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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/ext/isomorfeus_ferret_ext/benchmark.c +9 -20
  3. data/ext/isomorfeus_ferret_ext/benchmarks_all.h +1 -2
  4. data/ext/isomorfeus_ferret_ext/bm_hash.c +1 -2
  5. data/ext/isomorfeus_ferret_ext/brotli_dec_decode.c +4 -2
  6. data/ext/isomorfeus_ferret_ext/brotli_enc_encode.c +3 -2
  7. data/ext/isomorfeus_ferret_ext/frb_analysis.c +4 -5
  8. data/ext/isomorfeus_ferret_ext/frb_field_info.c +3 -4
  9. data/ext/isomorfeus_ferret_ext/frb_index.c +118 -125
  10. data/ext/isomorfeus_ferret_ext/frb_lazy_doc.c +14 -16
  11. data/ext/isomorfeus_ferret_ext/frb_search.c +31 -23
  12. data/ext/isomorfeus_ferret_ext/frb_store.c +27 -13
  13. data/ext/isomorfeus_ferret_ext/frb_utils.c +3 -6
  14. data/ext/isomorfeus_ferret_ext/frt_analysis.c +39 -46
  15. data/ext/isomorfeus_ferret_ext/frt_analysis.h +9 -9
  16. data/ext/isomorfeus_ferret_ext/frt_array.c +11 -22
  17. data/ext/isomorfeus_ferret_ext/frt_bitvector.h +3 -6
  18. data/ext/isomorfeus_ferret_ext/frt_doc_field.c +87 -0
  19. data/ext/isomorfeus_ferret_ext/frt_doc_field.h +26 -0
  20. data/ext/isomorfeus_ferret_ext/frt_document.c +4 -97
  21. data/ext/isomorfeus_ferret_ext/frt_document.h +2 -27
  22. data/ext/isomorfeus_ferret_ext/frt_except.c +8 -6
  23. data/ext/isomorfeus_ferret_ext/frt_except.h +1 -2
  24. data/ext/isomorfeus_ferret_ext/frt_field_index.c +13 -32
  25. data/ext/isomorfeus_ferret_ext/frt_field_index.h +0 -6
  26. data/ext/isomorfeus_ferret_ext/frt_field_info.c +69 -0
  27. data/ext/isomorfeus_ferret_ext/frt_field_info.h +49 -0
  28. data/ext/isomorfeus_ferret_ext/frt_field_infos.c +196 -0
  29. data/ext/isomorfeus_ferret_ext/frt_field_infos.h +35 -0
  30. data/ext/isomorfeus_ferret_ext/frt_global.c +10 -4
  31. data/ext/isomorfeus_ferret_ext/frt_global.h +11 -15
  32. data/ext/isomorfeus_ferret_ext/frt_hash.c +8 -8
  33. data/ext/isomorfeus_ferret_ext/frt_hash.h +1 -2
  34. data/ext/isomorfeus_ferret_ext/frt_hashset.c +20 -40
  35. data/ext/isomorfeus_ferret_ext/frt_hashset.h +1 -2
  36. data/ext/isomorfeus_ferret_ext/frt_helper.c +7 -15
  37. data/ext/isomorfeus_ferret_ext/frt_in_stream.c +35 -45
  38. data/ext/isomorfeus_ferret_ext/frt_in_stream.h +3 -2
  39. data/ext/isomorfeus_ferret_ext/frt_ind.c +20 -38
  40. data/ext/isomorfeus_ferret_ext/frt_index.c +292 -790
  41. data/ext/isomorfeus_ferret_ext/frt_index.h +1 -102
  42. data/ext/isomorfeus_ferret_ext/frt_lang.c +5 -10
  43. data/ext/isomorfeus_ferret_ext/frt_lazy_doc.c +3 -3
  44. data/ext/isomorfeus_ferret_ext/frt_lazy_doc.h +1 -1
  45. data/ext/isomorfeus_ferret_ext/frt_lazy_doc_field.c +18 -25
  46. data/ext/isomorfeus_ferret_ext/frt_lazy_doc_field.h +5 -5
  47. data/ext/isomorfeus_ferret_ext/frt_mdbx_store.c +102 -70
  48. data/ext/isomorfeus_ferret_ext/frt_mempool.c +8 -16
  49. data/ext/isomorfeus_ferret_ext/frt_multimapper.c +23 -46
  50. data/ext/isomorfeus_ferret_ext/frt_multimapper.h +4 -8
  51. data/ext/isomorfeus_ferret_ext/frt_out_stream.c +31 -43
  52. data/ext/isomorfeus_ferret_ext/frt_out_stream.h +2 -2
  53. data/ext/isomorfeus_ferret_ext/frt_posh.c +6 -819
  54. data/ext/isomorfeus_ferret_ext/frt_posh.h +0 -57
  55. data/ext/isomorfeus_ferret_ext/frt_priorityqueue.c +11 -22
  56. data/ext/isomorfeus_ferret_ext/frt_priorityqueue.h +1 -2
  57. data/ext/isomorfeus_ferret_ext/frt_q_boolean.c +85 -171
  58. data/ext/isomorfeus_ferret_ext/frt_q_match_all.c +8 -16
  59. data/ext/isomorfeus_ferret_ext/frt_q_multi_term.c +1 -2
  60. data/ext/isomorfeus_ferret_ext/frt_q_parser.c +49 -98
  61. data/ext/isomorfeus_ferret_ext/frt_q_phrase.c +52 -104
  62. data/ext/isomorfeus_ferret_ext/frt_q_range.c +6 -12
  63. data/ext/isomorfeus_ferret_ext/frt_q_span.c +113 -226
  64. data/ext/isomorfeus_ferret_ext/frt_q_wildcard.c +1 -2
  65. data/ext/isomorfeus_ferret_ext/frt_ram_store.c +134 -85
  66. data/ext/isomorfeus_ferret_ext/frt_search.c +82 -164
  67. data/ext/isomorfeus_ferret_ext/frt_similarity.c +11 -22
  68. data/ext/isomorfeus_ferret_ext/frt_similarity.h +1 -2
  69. data/ext/isomorfeus_ferret_ext/frt_store.c +13 -25
  70. data/ext/isomorfeus_ferret_ext/frt_store.h +86 -52
  71. data/ext/isomorfeus_ferret_ext/frt_term_vectors.c +8 -16
  72. data/ext/isomorfeus_ferret_ext/frt_win32.h +5 -10
  73. data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.c +12 -11
  74. data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.h +11 -13
  75. data/ext/isomorfeus_ferret_ext/lz4.c +422 -195
  76. data/ext/isomorfeus_ferret_ext/lz4.h +114 -46
  77. data/ext/isomorfeus_ferret_ext/lz4frame.c +421 -242
  78. data/ext/isomorfeus_ferret_ext/lz4frame.h +122 -53
  79. data/ext/isomorfeus_ferret_ext/lz4hc.c +127 -111
  80. data/ext/isomorfeus_ferret_ext/lz4hc.h +14 -14
  81. data/ext/isomorfeus_ferret_ext/lz4xxhash.h +1 -1
  82. data/ext/isomorfeus_ferret_ext/mdbx.c +3762 -2526
  83. data/ext/isomorfeus_ferret_ext/mdbx.h +115 -70
  84. data/ext/isomorfeus_ferret_ext/test.c +40 -87
  85. data/ext/isomorfeus_ferret_ext/test.h +3 -6
  86. data/ext/isomorfeus_ferret_ext/test_1710.c +11 -13
  87. data/ext/isomorfeus_ferret_ext/test_analysis.c +32 -64
  88. data/ext/isomorfeus_ferret_ext/test_array.c +6 -12
  89. data/ext/isomorfeus_ferret_ext/test_bitvector.c +12 -24
  90. data/ext/isomorfeus_ferret_ext/test_document.c +23 -33
  91. data/ext/isomorfeus_ferret_ext/test_except.c +10 -21
  92. data/ext/isomorfeus_ferret_ext/test_fields.c +62 -68
  93. data/ext/isomorfeus_ferret_ext/test_file_deleter.c +15 -23
  94. data/ext/isomorfeus_ferret_ext/test_filter.c +17 -27
  95. data/ext/isomorfeus_ferret_ext/test_global.c +14 -29
  96. data/ext/isomorfeus_ferret_ext/test_hash.c +19 -38
  97. data/ext/isomorfeus_ferret_ext/test_hashset.c +8 -16
  98. data/ext/isomorfeus_ferret_ext/test_helper.c +4 -8
  99. data/ext/isomorfeus_ferret_ext/test_highlighter.c +16 -28
  100. data/ext/isomorfeus_ferret_ext/test_index.c +277 -487
  101. data/ext/isomorfeus_ferret_ext/test_lang.c +7 -14
  102. data/ext/isomorfeus_ferret_ext/test_mdbx_store.c +2 -5
  103. data/ext/isomorfeus_ferret_ext/test_mempool.c +5 -10
  104. data/ext/isomorfeus_ferret_ext/test_multimapper.c +3 -6
  105. data/ext/isomorfeus_ferret_ext/test_priorityqueue.c +9 -18
  106. data/ext/isomorfeus_ferret_ext/test_q_const_score.c +4 -6
  107. data/ext/isomorfeus_ferret_ext/test_q_filtered.c +3 -4
  108. data/ext/isomorfeus_ferret_ext/test_q_fuzzy.c +9 -15
  109. data/ext/isomorfeus_ferret_ext/test_q_parser.c +8 -16
  110. data/ext/isomorfeus_ferret_ext/test_q_span.c +19 -35
  111. data/ext/isomorfeus_ferret_ext/test_ram_store.c +14 -13
  112. data/ext/isomorfeus_ferret_ext/test_search.c +60 -109
  113. data/ext/isomorfeus_ferret_ext/test_segments.c +8 -13
  114. data/ext/isomorfeus_ferret_ext/test_similarity.c +2 -4
  115. data/ext/isomorfeus_ferret_ext/test_sort.c +14 -24
  116. data/ext/isomorfeus_ferret_ext/test_store.c +96 -115
  117. data/ext/isomorfeus_ferret_ext/test_term.c +9 -15
  118. data/ext/isomorfeus_ferret_ext/test_term_vectors.c +9 -14
  119. data/ext/isomorfeus_ferret_ext/test_test.c +4 -8
  120. data/ext/isomorfeus_ferret_ext/test_threading.c +14 -20
  121. data/ext/isomorfeus_ferret_ext/testhelper.c +11 -21
  122. data/ext/isomorfeus_ferret_ext/testhelper.h +1 -1
  123. data/ext/isomorfeus_ferret_ext/tests_all.h +1 -2
  124. data/lib/isomorfeus/ferret/index/index.rb +1 -1
  125. data/lib/isomorfeus/ferret/version.rb +1 -1
  126. metadata +24 -4
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  LZ4 - Fast LZ compression algorithm
3
- Copyright (C) 2011-present, Yann Collet.
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
- #ifdef LZ4_USER_MEMORY_FUNCTIONS
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
- #include <string.h> /* memset, memcpy */
208
- #define MEM_INIT(p,v,s) memset((p),(v),(s))
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(__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)
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)) unalign;
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 unalign*)ptr)->u16; }
349
- static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
350
- static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; }
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) { ((unalign*)memPtr)->u16 = value; }
353
- static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)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 on certain
426
- * mobile chipsets, performance is reduced with clang. For information
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 : Like usingExtDict, but everything concerning the preceding
656
- * content is in a separate context, pointed to by
657
- * ctx->dictCtx. ctx->dictionary, ctx->dictSize, and table
658
- * entries in the current context that refer to positions
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 LZ4_STREAMSIZE; }
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, is faster
831
- * than compressing without a gap. However, compressing with
832
- * currentOffset == 0 is faster still, so we preserve that case.
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 *inputConsumed, /* only written when outputDirective == fillOutput */
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 = !dictionary ? NULL : (dictDirective == usingDictCtx) ?
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 occurence; can be within current prefix, or within extDict
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(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
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
- const LZ4_stream_t_internal* dictCtx = dictionaryStream == NULL ? NULL :
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 BYTE* dictEnd = streamPtr->dictionary + streamPtr->dictSize;
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); /* avoid index overflow */
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-1 < 4-1) /* intentional underflow */
1582
- && (dictEnd != (const BYTE*)source) ) {
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 = (const BYTE*)source;
1657
+ dictEnd = source;
1587
1658
  }
1588
1659
 
1589
1660
  /* Check overlapping input/dictionary space */
1590
- { const BYTE* sourceEnd = (const BYTE*) source + inputSize;
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 == (const BYTE*)source) {
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 : you don't need to call LZ4_loadDict() afterwards,
1665
- * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue().
1666
- * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
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
- const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
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
- memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
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 - pointer to use as input.
1701
- * lencheck - end ip. Return an error if ip advances >= lencheck.
1702
- * loop_check - check ip >= lencheck in body of loop. Returns loop_error if so.
1703
- * initial_check - check ip >= lencheck before start of loop. Returns initial_error if so.
1704
- * error (output) - error code. Should be set to 0 before call.
1705
- */
1706
- typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error;
1707
- LZ4_FORCE_INLINE unsigned
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;
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 (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
1723
- *error = loop_error;
1724
- return length;
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 safeDecode = (endOnInput==endOnInputSize);
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 - (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/;
1769
- const BYTE* const shortoend = oend - (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/;
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 ((endOnInput) && (unlikely(outputSize==0))) {
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 ((!endOnInput) && (unlikely(outputSize==0))) { return (*ip==0 ? 1 : -1); }
1787
- if ((endOnInput) && unlikely(srcSize==0)) { return -1; }
1983
+ if (unlikely(srcSize==0)) { return -1; }
1788
1984
 
1789
- /* Currently the fast loop shows a regression on qualcomm arm chips. */
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 < iend-FASTLOOP_SAFE_DISTANCE */
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
- if (endOnInput) { assert(ip < iend); }
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
- variable_length_error error = ok;
1809
- length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
1810
- if (error == initial_error) { goto _output_error; }
1811
- if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
1812
- if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
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 (endOnInput) { /* LZ4_decompress_safe() */
1818
- if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }
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
- if (endOnInput) { /* LZ4_decompress_safe() */
1829
- DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length);
1830
- /* We don't need to check oend, since we check it once for each loop below */
1831
- if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; }
1832
- /* Literals can only be 14, but hope compilers optimize if we copy by a register size */
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
- 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; }
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: Avoids a branch in LZ4_wildCopy32 if true */
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
- memmove(op, dictEnd - (lowPrefix-match), length);
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 ( (endOnInput ? length != RUN_MASK : length <= 8)
2128
+ if ( (length != RUN_MASK)
1945
2129
  /* strictly "less than" on input, to re-enter the loop with at least one byte */
1946
- && likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend)) ) {
2130
+ && likely((ip < shortiend) & (op <= shortoend)) ) {
1947
2131
  /* Copy the literals */
1948
- LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
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
- variable_length_error error = ok;
1979
- length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
1980
- if (error == initial_error) { goto _output_error; }
1981
- if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */
1982
- if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */
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 ( ((endOnInput) && ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) )
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 ((endOnInput) && ((ip+length != iend) || (cpy > oend))) {
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
- memmove(op, ip, length); /* supports overlapping memory regions; only matters for in-place decompression scenarios */
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); /* may overwrite up to WILDCOPYLENGTH beyond 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
- variable_length_error error = ok;
2064
- length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);
2065
- if (error != ok) goto _output_error;
2066
- if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */
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
- memmove(op, dictEnd - (lowPrefix-match), length);
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
- if (endOnInput) {
2155
- DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst));
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
- endOnInputSize, decode_full_block, noDict,
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
- endOnInputSize, partial_decode,
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
- return LZ4_decompress_generic(source, dest, 0, originalSize,
2191
- endOnOutputSize, decode_full_block, withPrefix64k,
2192
- (BYTE*)dest - 64 KB, NULL, 0);
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
- endOnInputSize, decode_full_block, withPrefix64k,
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
- /* LZ4_decompress_fast doesn't validate match offsets,
2209
- * and thus serves well with any prefixed dictionary. */
2210
- return LZ4_decompress_fast(source, dest, originalSize);
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
- endOnInputSize, decode_full_block, noDict,
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
- endOnInputSize, decode_full_block, usingExtDict,
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 LZ4_decompress_generic(source, dest, 0, originalSize,
2237
- endOnOutputSize, decode_full_block, usingExtDict,
2238
- (BYTE*)dest, (const BYTE*)dictStart, dictSize);
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
- endOnInputSize, decode_full_block, usingExtDict,
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
- LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));
2268
- LZ4_STATIC_ASSERT(LZ4_STREAMDECODESIZE >= sizeof(LZ4_streamDecode_t_internal)); /* A compilation error here means LZ4_STREAMDECODESIZE is not large enough */
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) dictSize;
2289
- lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
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
- int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
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 = &LZ4_streamDecode->internal_donotuse;
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
- if (lz4sd->prefixSize >= 64 KB - 1 || lz4sd->extDictSize == 0)
2376
- result = LZ4_decompress_fast(source, dest, originalSize);
2377
- else
2378
- result = LZ4_decompress_fast_doubleDict(source, dest, originalSize,
2379
- lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
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 LZ4_decompress_fast(source, dest, originalSize);
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 LZ4_STREAMSIZE; }
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
  {