isomorfeus-ferret 0.17.2 → 0.17.3

Sign up to get free protection for your applications and to get access to all the features.
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
  {