extlz4 0.2.5 → 0.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.
@@ -1,41 +1,44 @@
1
1
  /*
2
- LZ4 auto-framing library
3
- Copyright (C) 2011-2016, Yann Collet.
4
-
5
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
-
7
- Redistribution and use in source and binary forms, with or without
8
- modification, are permitted provided that the following conditions are
9
- met:
10
-
11
- * Redistributions of source code must retain the above copyright
12
- notice, this list of conditions and the following disclaimer.
13
- * Redistributions in binary form must reproduce the above
14
- copyright notice, this list of conditions and the following disclaimer
15
- in the documentation and/or other materials provided with the
16
- distribution.
17
-
18
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
-
30
- You can contact the author at :
31
- - LZ4 homepage : http://www.lz4.org
32
- - LZ4 source repository : https://github.com/lz4/lz4
33
- */
2
+ * LZ4 auto-framing library
3
+ * Copyright (C) 2011-2016, Yann Collet.
4
+ *
5
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are
9
+ * met:
10
+ *
11
+ * - Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ * - Redistributions in binary form must reproduce the above
14
+ * copyright notice, this list of conditions and the following disclaimer
15
+ * in the documentation and/or other materials provided with the
16
+ * distribution.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ * You can contact the author at :
31
+ * - LZ4 homepage : http://www.lz4.org
32
+ * - LZ4 source repository : https://github.com/lz4/lz4
33
+ */
34
34
 
35
35
  /* LZ4F is a stand-alone API to create LZ4-compressed Frames
36
- * in full conformance with specification v1.5.0
37
- * All related operations, including memory management, are handled by the library.
38
- * */
36
+ * in full conformance with specification v1.6.1 .
37
+ * This library rely upon memory management capabilities (malloc, free)
38
+ * provided either by <stdlib.h>,
39
+ * or redirected towards another library of user's choice
40
+ * (see Memory Routines below).
41
+ */
39
42
 
40
43
 
41
44
  /*-************************************
@@ -46,20 +49,47 @@ You can contact the author at :
46
49
  #endif
47
50
 
48
51
 
52
+ /*-************************************
53
+ * Tuning parameters
54
+ **************************************/
55
+ /*
56
+ * LZ4F_HEAPMODE :
57
+ * Select how default compression functions will allocate memory for their hash table,
58
+ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
59
+ */
60
+ #ifndef LZ4F_HEAPMODE
61
+ # define LZ4F_HEAPMODE 0
62
+ #endif
63
+
64
+
49
65
  /*-************************************
50
66
  * Memory routines
51
67
  **************************************/
68
+ /*
69
+ * User may redirect invocations of
70
+ * malloc(), calloc() and free()
71
+ * towards another library or solution of their choice
72
+ * by modifying below section.
73
+ */
52
74
  #include <stdlib.h> /* malloc, calloc, free */
53
- #define ALLOCATOR(s) calloc(1,s)
54
- #define FREEMEM free
75
+ #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
76
+ # define ALLOC(s) malloc(s)
77
+ # define ALLOC_AND_ZERO(s) calloc(1,(s))
78
+ # define FREEMEM(p) free(p)
79
+ #endif
80
+
55
81
  #include <string.h> /* memset, memcpy, memmove */
56
- #define MEM_INIT memset
82
+ #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
83
+ # define MEM_INIT(p,v,s) memset((p),(v),(s))
84
+ #endif
57
85
 
58
86
 
59
87
  /*-************************************
60
- * Includes
88
+ * Library declarations
61
89
  **************************************/
62
- #include "lz4frame_static.h"
90
+ #define LZ4F_STATIC_LINKING_ONLY
91
+ #include "lz4frame.h"
92
+ #define LZ4_STATIC_LINKING_ONLY
63
93
  #include "lz4.h"
64
94
  #define LZ4_HC_STATIC_LINKING_ONLY
65
95
  #include "lz4hc.h"
@@ -70,8 +100,29 @@ You can contact the author at :
70
100
  /*-************************************
71
101
  * Debug
72
102
  **************************************/
103
+ #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)
104
+ # include <assert.h>
105
+ #else
106
+ # ifndef assert
107
+ # define assert(condition) ((void)0)
108
+ # endif
109
+ #endif
110
+
73
111
  #define LZ4F_STATIC_ASSERT(c) { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
74
112
 
113
+ #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) && !defined(DEBUGLOG)
114
+ # include <stdio.h>
115
+ static int g_debuglog_enable = 1;
116
+ # define DEBUGLOG(l, ...) { \
117
+ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \
118
+ fprintf(stderr, __FILE__ ": "); \
119
+ fprintf(stderr, __VA_ARGS__); \
120
+ fprintf(stderr, " \n"); \
121
+ } }
122
+ #else
123
+ # define DEBUGLOG(l, ...) {} /* disabled */
124
+ #endif
125
+
75
126
 
76
127
  /*-************************************
77
128
  * Basic Types
@@ -97,8 +148,8 @@ static U32 LZ4F_readLE32 (const void* src)
97
148
  {
98
149
  const BYTE* const srcPtr = (const BYTE*)src;
99
150
  U32 value32 = srcPtr[0];
100
- value32 += (srcPtr[1]<<8);
101
- value32 += (srcPtr[2]<<16);
151
+ value32 += ((U32)srcPtr[1])<< 8;
152
+ value32 += ((U32)srcPtr[2])<<16;
102
153
  value32 += ((U32)srcPtr[3])<<24;
103
154
  return value32;
104
155
  }
@@ -143,9 +194,11 @@ static void LZ4F_writeLE64 (void* dst, U64 value64)
143
194
  /*-************************************
144
195
  * Constants
145
196
  **************************************/
146
- #define KB *(1<<10)
147
- #define MB *(1<<20)
148
- #define GB *(1<<30)
197
+ #ifndef LZ4_SRC_INCLUDED /* avoid double definition */
198
+ # define KB *(1<<10)
199
+ # define MB *(1<<20)
200
+ # define GB *(1<<30)
201
+ #endif
149
202
 
150
203
  #define _1BIT 0x01
151
204
  #define _2BITS 0x03
@@ -158,9 +211,10 @@ static void LZ4F_writeLE64 (void* dst, U64 value64)
158
211
  #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
159
212
  #define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB
160
213
 
161
- static const size_t minFHSize = 7;
214
+ static const size_t minFHSize = LZ4F_HEADER_SIZE_MIN; /* 7 */
162
215
  static const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX; /* 19 */
163
- static const size_t BHSize = 4;
216
+ static const size_t BHSize = 4; /* block header : size, and compress flag */
217
+ static const size_t BFSize = 4; /* block footer : checksum (optional) */
164
218
 
165
219
 
166
220
  /*-************************************
@@ -180,7 +234,8 @@ typedef struct LZ4F_cctx_s
180
234
  U64 totalInSize;
181
235
  XXH32_state_t xxh;
182
236
  void* lz4CtxPtr;
183
- U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
237
+ U16 lz4CtxAlloc; /* sized for: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */
238
+ U16 lz4CtxState; /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */
184
239
  } LZ4F_cctx_t;
185
240
 
186
241
 
@@ -220,22 +275,22 @@ unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; }
220
275
 
221
276
  int LZ4F_compressionLevel_max(void) { return LZ4HC_CLEVEL_MAX; }
222
277
 
223
-
224
- /*-************************************
225
- * Private functions
226
- **************************************/
227
- #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
228
-
229
- static size_t LZ4F_getBlockSize(unsigned blockSizeID)
278
+ size_t LZ4F_getBlockSize(unsigned blockSizeID)
230
279
  {
231
280
  static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };
232
281
 
233
282
  if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
234
- blockSizeID -= 4;
235
- if (blockSizeID > 3) return err0r(LZ4F_ERROR_maxBlockSize_invalid);
283
+ if (blockSizeID < LZ4F_max64KB || blockSizeID > LZ4F_max4MB)
284
+ return err0r(LZ4F_ERROR_maxBlockSize_invalid);
285
+ blockSizeID -= LZ4F_max64KB;
236
286
  return blockSizes[blockSizeID];
237
287
  }
238
288
 
289
+ /*-************************************
290
+ * Private functions
291
+ **************************************/
292
+ #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
293
+
239
294
  static BYTE LZ4F_headerChecksum (const void* header, size_t length)
240
295
  {
241
296
  U32 const xxh = XXH32(header, length, 0);
@@ -271,7 +326,7 @@ static size_t LZ4F_compressBound_internal(size_t srcSize,
271
326
  size_t alreadyBuffered)
272
327
  {
273
328
  LZ4F_preferences_t prefsNull;
274
- memset(&prefsNull, 0, sizeof(prefsNull));
329
+ MEM_INIT(&prefsNull, 0, sizeof(prefsNull));
275
330
  prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */
276
331
  { const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
277
332
  U32 const flush = prefsPtr->autoFlush | (srcSize==0);
@@ -281,15 +336,14 @@ static size_t LZ4F_compressBound_internal(size_t srcSize,
281
336
  size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered);
282
337
  size_t const maxSrcSize = srcSize + bufferedSize;
283
338
  unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize);
284
- size_t const partialBlockSize = (srcSize - (srcSize==0)) & (blockSize-1); /* 0 => -1 == MAX => blockSize-1 */
339
+ size_t const partialBlockSize = maxSrcSize & (blockSize-1);
285
340
  size_t const lastBlockSize = flush ? partialBlockSize : 0;
286
341
  unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0);
287
342
 
288
- size_t const blockHeaderSize = 4;
289
- size_t const blockCRCSize = 4 * prefsPtr->frameInfo.blockChecksumFlag;
290
- size_t const frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
343
+ size_t const blockCRCSize = BFSize * prefsPtr->frameInfo.blockChecksumFlag;
344
+ size_t const frameEnd = BHSize + (prefsPtr->frameInfo.contentChecksumFlag*BFSize);
291
345
 
292
- return ((blockHeaderSize + blockCRCSize) * nbBlocks) +
346
+ return ((BHSize + blockCRCSize) * nbBlocks) +
293
347
  (blockSize * nbFullBlocks) + lastBlockSize + frameEnd;
294
348
  }
295
349
  }
@@ -300,7 +354,7 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
300
354
  size_t const headerSize = maxFHSize; /* max header size, including optional fields */
301
355
 
302
356
  if (preferencesPtr!=NULL) prefs = *preferencesPtr;
303
- else memset(&prefs, 0, sizeof(prefs));
357
+ else MEM_INIT(&prefs, 0, sizeof(prefs));
304
358
  prefs.autoFlush = 1;
305
359
 
306
360
  return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);;
@@ -316,27 +370,22 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
316
370
  * @return : number of bytes written into dstBuffer,
317
371
  * or an error code if it fails (can be tested using LZ4F_isError())
318
372
  */
319
- size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity,
373
+ size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx,
374
+ void* dstBuffer, size_t dstCapacity,
320
375
  const void* srcBuffer, size_t srcSize,
321
376
  const LZ4F_CDict* cdict,
322
377
  const LZ4F_preferences_t* preferencesPtr)
323
378
  {
324
- LZ4F_cctx_t cctxI;
325
- LZ4_stream_t lz4ctx; /* pretty large on stack */
326
379
  LZ4F_preferences_t prefs;
327
380
  LZ4F_compressOptions_t options;
328
381
  BYTE* const dstStart = (BYTE*) dstBuffer;
329
382
  BYTE* dstPtr = dstStart;
330
383
  BYTE* const dstEnd = dstStart + dstCapacity;
331
384
 
332
- memset(&cctxI, 0, sizeof(cctxI));
333
- cctxI.version = LZ4F_VERSION;
334
- cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */
335
-
336
385
  if (preferencesPtr!=NULL)
337
386
  prefs = *preferencesPtr;
338
387
  else
339
- memset(&prefs, 0, sizeof(prefs));
388
+ MEM_INIT(&prefs, 0, sizeof(prefs));
340
389
  if (prefs.frameInfo.contentSize != 0)
341
390
  prefs.frameInfo.contentSize = (U64)srcSize; /* auto-correct content size if selected (!=0) */
342
391
 
@@ -345,33 +394,28 @@ size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity,
345
394
  if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))
346
395
  prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* only one block => no need for inter-block link */
347
396
 
348
- if (prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
349
- cctxI.lz4CtxPtr = &lz4ctx;
350
- cctxI.lz4CtxLevel = 1;
351
- } /* fast compression context pre-created on stack */
352
-
353
- memset(&options, 0, sizeof(options));
397
+ MEM_INIT(&options, 0, sizeof(options));
354
398
  options.stableSrc = 1;
355
399
 
356
400
  if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs)) /* condition to guarantee success */
357
401
  return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
358
402
 
359
- { size_t const headerSize = LZ4F_compressBegin_usingCDict(&cctxI, dstBuffer, dstCapacity, cdict, &prefs); /* write header */
403
+ { size_t const headerSize = LZ4F_compressBegin_usingCDict(cctx, dstBuffer, dstCapacity, cdict, &prefs); /* write header */
360
404
  if (LZ4F_isError(headerSize)) return headerSize;
361
405
  dstPtr += headerSize; /* header size */ }
362
406
 
363
- { size_t const cSize = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);
407
+ assert(dstEnd >= dstPtr);
408
+ { size_t const cSize = LZ4F_compressUpdate(cctx, dstPtr, (size_t)(dstEnd-dstPtr), srcBuffer, srcSize, &options);
364
409
  if (LZ4F_isError(cSize)) return cSize;
365
410
  dstPtr += cSize; }
366
411
 
367
- { size_t const tailSize = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
412
+ assert(dstEnd >= dstPtr);
413
+ { size_t const tailSize = LZ4F_compressEnd(cctx, dstPtr, (size_t)(dstEnd-dstPtr), &options); /* flush last block, and generate suffix */
368
414
  if (LZ4F_isError(tailSize)) return tailSize;
369
415
  dstPtr += tailSize; }
370
416
 
371
- if (prefs.compressionLevel >= LZ4HC_CLEVEL_MIN) /* Ctx allocation only for lz4hc */
372
- FREEMEM(cctxI.lz4CtxPtr);
373
-
374
- return (dstPtr - dstStart);
417
+ assert(dstEnd >= dstStart);
418
+ return (size_t)(dstPtr - dstStart);
375
419
  }
376
420
 
377
421
 
@@ -386,9 +430,44 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,
386
430
  const void* srcBuffer, size_t srcSize,
387
431
  const LZ4F_preferences_t* preferencesPtr)
388
432
  {
389
- return LZ4F_compressFrame_usingCDict(dstBuffer, dstCapacity,
390
- srcBuffer, srcSize,
391
- NULL, preferencesPtr);
433
+ size_t result;
434
+ #if (LZ4F_HEAPMODE)
435
+ LZ4F_cctx_t *cctxPtr;
436
+ result = LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION);
437
+ if (LZ4F_isError(result)) return result;
438
+ #else
439
+ LZ4F_cctx_t cctx;
440
+ LZ4_stream_t lz4ctx;
441
+ LZ4F_cctx_t *cctxPtr = &cctx;
442
+
443
+ DEBUGLOG(4, "LZ4F_compressFrame");
444
+ MEM_INIT(&cctx, 0, sizeof(cctx));
445
+ cctx.version = LZ4F_VERSION;
446
+ cctx.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */
447
+ if (preferencesPtr == NULL ||
448
+ preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN)
449
+ {
450
+ LZ4_initStream(&lz4ctx, sizeof(lz4ctx));
451
+ cctxPtr->lz4CtxPtr = &lz4ctx;
452
+ cctxPtr->lz4CtxAlloc = 1;
453
+ cctxPtr->lz4CtxState = 1;
454
+ }
455
+ #endif
456
+
457
+ result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity,
458
+ srcBuffer, srcSize,
459
+ NULL, preferencesPtr);
460
+
461
+ #if (LZ4F_HEAPMODE)
462
+ LZ4F_freeCompressionContext(cctxPtr);
463
+ #else
464
+ if (preferencesPtr != NULL &&
465
+ preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN)
466
+ {
467
+ FREEMEM(cctxPtr->lz4CtxPtr);
468
+ }
469
+ #endif
470
+ return result;
392
471
  }
393
472
 
394
473
 
@@ -411,13 +490,14 @@ struct LZ4F_CDict_s {
411
490
  LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize)
412
491
  {
413
492
  const char* dictStart = (const char*)dictBuffer;
414
- LZ4F_CDict* cdict = (LZ4F_CDict*) malloc(sizeof(*cdict));
493
+ LZ4F_CDict* cdict = (LZ4F_CDict*) ALLOC(sizeof(*cdict));
494
+ DEBUGLOG(4, "LZ4F_createCDict");
415
495
  if (!cdict) return NULL;
416
496
  if (dictSize > 64 KB) {
417
497
  dictStart += dictSize - 64 KB;
418
498
  dictSize = 64 KB;
419
499
  }
420
- cdict->dictContent = ALLOCATOR(dictSize);
500
+ cdict->dictContent = ALLOC(dictSize);
421
501
  cdict->fastCtx = LZ4_createStream();
422
502
  cdict->HCCtx = LZ4_createStreamHC();
423
503
  if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) {
@@ -425,9 +505,8 @@ LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize)
425
505
  return NULL;
426
506
  }
427
507
  memcpy(cdict->dictContent, dictStart, dictSize);
428
- LZ4_resetStream(cdict->fastCtx);
429
508
  LZ4_loadDict (cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize);
430
- LZ4_resetStreamHC(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT);
509
+ LZ4_setCompressionLevel(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT);
431
510
  LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize);
432
511
  return cdict;
433
512
  }
@@ -456,7 +535,7 @@ void LZ4F_freeCDict(LZ4F_CDict* cdict)
456
535
  */
457
536
  LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
458
537
  {
459
- LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOCATOR(sizeof(LZ4F_cctx_t));
538
+ LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t));
460
539
  if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
461
540
 
462
541
  cctxPtr->version = version;
@@ -482,6 +561,36 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp
482
561
  }
483
562
 
484
563
 
564
+ /**
565
+ * This function prepares the internal LZ4(HC) stream for a new compression,
566
+ * resetting the context and attaching the dictionary, if there is one.
567
+ *
568
+ * It needs to be called at the beginning of each independent compression
569
+ * stream (i.e., at the beginning of a frame in blockLinked mode, or at the
570
+ * beginning of each block in blockIndependent mode).
571
+ */
572
+ static void LZ4F_initStream(void* ctx,
573
+ const LZ4F_CDict* cdict,
574
+ int level,
575
+ LZ4F_blockMode_t blockMode) {
576
+ if (level < LZ4HC_CLEVEL_MIN) {
577
+ if (cdict != NULL || blockMode == LZ4F_blockLinked) {
578
+ /* In these cases, we will call LZ4_compress_fast_continue(),
579
+ * which needs an already reset context. Otherwise, we'll call a
580
+ * one-shot API. The non-continued APIs internally perform their own
581
+ * resets at the beginning of their calls, where they know what
582
+ * tableType they need the context to be in. So in that case this
583
+ * would be misguided / wasted work. */
584
+ LZ4_resetStream_fast((LZ4_stream_t*)ctx);
585
+ }
586
+ LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL);
587
+ } else {
588
+ LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level);
589
+ LZ4_attach_HC_dictionary((LZ4_streamHC_t *)ctx, cdict ? cdict->HCCtx : NULL);
590
+ }
591
+ }
592
+
593
+
485
594
  /*! LZ4F_compressBegin_usingCDict() :
486
595
  * init streaming compression and writes frame header into dstBuffer.
487
596
  * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
@@ -499,21 +608,35 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
499
608
  BYTE* headerStart;
500
609
 
501
610
  if (dstCapacity < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
502
- memset(&prefNull, 0, sizeof(prefNull));
611
+ MEM_INIT(&prefNull, 0, sizeof(prefNull));
503
612
  if (preferencesPtr == NULL) preferencesPtr = &prefNull;
504
613
  cctxPtr->prefs = *preferencesPtr;
505
614
 
506
615
  /* Ctx Management */
507
- { U32 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */
508
- if (cctxPtr->lz4CtxLevel < ctxTypeID) {
616
+ { U16 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2;
617
+ if (cctxPtr->lz4CtxAlloc < ctxTypeID) {
509
618
  FREEMEM(cctxPtr->lz4CtxPtr);
510
- if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
511
- cctxPtr->lz4CtxPtr = (void*)LZ4_createStream();
512
- else
513
- cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC();
514
- if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed);
515
- cctxPtr->lz4CtxLevel = ctxTypeID;
516
- } }
619
+ if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
620
+ cctxPtr->lz4CtxPtr = LZ4_createStream();
621
+ } else {
622
+ cctxPtr->lz4CtxPtr = LZ4_createStreamHC();
623
+ }
624
+ if (cctxPtr->lz4CtxPtr == NULL)
625
+ return err0r(LZ4F_ERROR_allocation_failed);
626
+ cctxPtr->lz4CtxAlloc = ctxTypeID;
627
+ cctxPtr->lz4CtxState = ctxTypeID;
628
+ } else if (cctxPtr->lz4CtxState != ctxTypeID) {
629
+ /* otherwise, a sufficient buffer is allocated, but we need to
630
+ * reset it to the correct context type */
631
+ if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
632
+ LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t));
633
+ } else {
634
+ LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t));
635
+ LZ4_setCompressionLevel((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
636
+ }
637
+ cctxPtr->lz4CtxState = ctxTypeID;
638
+ }
639
+ }
517
640
 
518
641
  /* Buffer Management */
519
642
  if (cctxPtr->prefs.frameInfo.blockSizeID == 0)
@@ -521,37 +644,28 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
521
644
  cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
522
645
 
523
646
  { size_t const requiredBuffSize = preferencesPtr->autoFlush ?
524
- (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 64 KB : /* only needs windows size */
525
- cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 128 KB);
647
+ ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */
648
+ cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0);
526
649
 
527
650
  if (cctxPtr->maxBufferSize < requiredBuffSize) {
528
651
  cctxPtr->maxBufferSize = 0;
529
652
  FREEMEM(cctxPtr->tmpBuff);
530
- cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);
653
+ cctxPtr->tmpBuff = (BYTE*)ALLOC_AND_ZERO(requiredBuffSize);
531
654
  if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed);
532
655
  cctxPtr->maxBufferSize = requiredBuffSize;
533
656
  } }
534
657
  cctxPtr->tmpIn = cctxPtr->tmpBuff;
535
658
  cctxPtr->tmpInSize = 0;
536
- XXH32_reset(&(cctxPtr->xxh), 0);
659
+ (void)XXH32_reset(&(cctxPtr->xxh), 0);
537
660
 
538
661
  /* context init */
539
662
  cctxPtr->cdict = cdict;
540
663
  if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) {
541
664
  /* frame init only for blockLinked : blockIndependent will be init at each block */
542
- if (cdict) {
543
- if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
544
- memcpy(cctxPtr->lz4CtxPtr, cdict->fastCtx, sizeof(*cdict->fastCtx));
545
- } else {
546
- memcpy(cctxPtr->lz4CtxPtr, cdict->HCCtx, sizeof(*cdict->HCCtx));
547
- LZ4_setCompressionLevel((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
548
- }
549
- } else {
550
- if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
551
- LZ4_resetStream((LZ4_stream_t*)(cctxPtr->lz4CtxPtr));
552
- else
553
- LZ4_resetStreamHC((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), cctxPtr->prefs.compressionLevel);
554
- }
665
+ LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked);
666
+ }
667
+ if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) {
668
+ LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed);
555
669
  }
556
670
 
557
671
  /* Magic Number */
@@ -563,7 +677,7 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
563
677
  *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */
564
678
  + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)
565
679
  + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4)
566
- + ((cctxPtr->prefs.frameInfo.contentSize > 0) << 3)
680
+ + ((unsigned)(cctxPtr->prefs.frameInfo.contentSize > 0) << 3)
567
681
  + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)
568
682
  + (cctxPtr->prefs.frameInfo.dictID > 0) );
569
683
  /* BD Byte */
@@ -580,11 +694,11 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
580
694
  dstPtr += 4;
581
695
  }
582
696
  /* Header CRC Byte */
583
- *dstPtr = LZ4F_headerChecksum(headerStart, dstPtr - headerStart);
697
+ *dstPtr = LZ4F_headerChecksum(headerStart, (size_t)(dstPtr - headerStart));
584
698
  dstPtr++;
585
699
 
586
700
  cctxPtr->cStage = 1; /* header written, now request input data block */
587
- return (dstPtr - dstStart);
701
+ return (size_t)(dstPtr - dstStart);
588
702
  }
589
703
 
590
704
 
@@ -593,7 +707,7 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
593
707
  * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
594
708
  * preferencesPtr can be NULL, in which case default parameters are selected.
595
709
  * @return : number of bytes written into dstBuffer for the header
596
- * or an error code (can be tested using LZ4F_isError())
710
+ * or an error code (can be tested using LZ4F_isError())
597
711
  */
598
712
  size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
599
713
  void* dstBuffer, size_t dstCapacity,
@@ -604,10 +718,10 @@ size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
604
718
  }
605
719
 
606
720
 
607
- /* LZ4F_compressBound() :
608
- * @ return size of Dst buffer given a srcSize to handle worst case situations.
609
- * The LZ4F_frameInfo_t structure is optional : if NULL, preferences will be set to cover worst case situations.
610
- * This function cannot fail.
721
+ /* LZ4F_compressBound() :
722
+ * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario.
723
+ * LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario.
724
+ * This function cannot fail.
611
725
  */
612
726
  size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
613
727
  {
@@ -619,55 +733,59 @@ typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize
619
733
 
620
734
 
621
735
  /*! LZ4F_makeBlock():
622
- * compress a single block, add header and checksum
623
- * assumption : dst buffer capacity is >= srcSize */
624
- static size_t LZ4F_makeBlock(void* dst, const void* src, size_t srcSize,
736
+ * compress a single block, add header and optional checksum.
737
+ * assumption : dst buffer capacity is >= BHSize + srcSize + crcSize
738
+ */
739
+ static size_t LZ4F_makeBlock(void* dst,
740
+ const void* src, size_t srcSize,
625
741
  compressFunc_t compress, void* lz4ctx, int level,
626
- const LZ4F_CDict* cdict, LZ4F_blockChecksum_t crcFlag)
742
+ const LZ4F_CDict* cdict,
743
+ LZ4F_blockChecksum_t crcFlag)
627
744
  {
628
745
  BYTE* const cSizePtr = (BYTE*)dst;
629
- U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4),
746
+ U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+BHSize),
630
747
  (int)(srcSize), (int)(srcSize-1),
631
748
  level, cdict);
632
- LZ4F_writeLE32(cSizePtr, cSize);
633
749
  if (cSize == 0) { /* compression failed */
634
750
  cSize = (U32)srcSize;
635
751
  LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);
636
- memcpy(cSizePtr+4, src, srcSize);
752
+ memcpy(cSizePtr+BHSize, src, srcSize);
753
+ } else {
754
+ LZ4F_writeLE32(cSizePtr, cSize);
637
755
  }
638
756
  if (crcFlag) {
639
- U32 const crc32 = XXH32(cSizePtr+4, cSize, 0); /* checksum of compressed data */
640
- LZ4F_writeLE32(cSizePtr+4+cSize, crc32);
757
+ U32 const crc32 = XXH32(cSizePtr+BHSize, cSize, 0); /* checksum of compressed data */
758
+ LZ4F_writeLE32(cSizePtr+BHSize+cSize, crc32);
641
759
  }
642
- return 4 + cSize + ((U32)crcFlag)*4;
760
+ return BHSize + cSize + ((U32)crcFlag)*BFSize;
643
761
  }
644
762
 
645
763
 
646
764
  static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
647
765
  {
648
- int const acceleration = (level < -1) ? -level : 1;
766
+ int const acceleration = (level < 0) ? -level + 1 : 1;
767
+ LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
649
768
  if (cdict) {
650
- memcpy(ctx, cdict->fastCtx, sizeof(*cdict->fastCtx));
651
769
  return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
770
+ } else {
771
+ return LZ4_compress_fast_extState_fastReset(ctx, src, dst, srcSize, dstCapacity, acceleration);
652
772
  }
653
- return LZ4_compress_fast_extState(ctx, src, dst, srcSize, dstCapacity, acceleration);
654
773
  }
655
774
 
656
775
  static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
657
776
  {
658
- int const acceleration = (level < -1) ? -level : 1;
777
+ int const acceleration = (level < 0) ? -level + 1 : 1;
659
778
  (void)cdict; /* init once at beginning of frame */
660
779
  return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
661
780
  }
662
781
 
663
782
  static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
664
783
  {
784
+ LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
665
785
  if (cdict) {
666
- memcpy(ctx, cdict->HCCtx, sizeof(*cdict->HCCtx));
667
- LZ4_setCompressionLevel((LZ4_streamHC_t*)ctx, level);
668
786
  return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
669
787
  }
670
- return LZ4_compress_HC_extStateHC(ctx, src, dst, srcSize, dstCapacity, level);
788
+ return LZ4_compress_HC_extStateHC_fastReset(ctx, src, dst, srcSize, dstCapacity, level);
671
789
  }
672
790
 
673
791
  static int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
@@ -716,10 +834,12 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
716
834
  LZ4F_lastBlockStatus lastBlockCompressed = notDone;
717
835
  compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
718
836
 
837
+ DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize);
719
838
 
720
839
  if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
721
- if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize)) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
722
- memset(&cOptionsNull, 0, sizeof(cOptionsNull));
840
+ if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
841
+ return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
842
+ MEM_INIT(&cOptionsNull, 0, sizeof(cOptionsNull));
723
843
  if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
724
844
 
725
845
  /* complete tmp buffer */
@@ -737,9 +857,11 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
737
857
  memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
738
858
  srcPtr += sizeToCopy;
739
859
 
740
- dstPtr += LZ4F_makeBlock(dstPtr, cctxPtr->tmpIn, blockSize,
860
+ dstPtr += LZ4F_makeBlock(dstPtr,
861
+ cctxPtr->tmpIn, blockSize,
741
862
  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
742
- cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
863
+ cctxPtr->cdict,
864
+ cctxPtr->prefs.frameInfo.blockChecksumFlag);
743
865
 
744
866
  if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
745
867
  cctxPtr->tmpInSize = 0;
@@ -749,18 +871,22 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
749
871
  while ((size_t)(srcEnd - srcPtr) >= blockSize) {
750
872
  /* compress full blocks */
751
873
  lastBlockCompressed = fromSrcBuffer;
752
- dstPtr += LZ4F_makeBlock(dstPtr, srcPtr, blockSize,
874
+ dstPtr += LZ4F_makeBlock(dstPtr,
875
+ srcPtr, blockSize,
753
876
  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
754
- cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
877
+ cctxPtr->cdict,
878
+ cctxPtr->prefs.frameInfo.blockChecksumFlag);
755
879
  srcPtr += blockSize;
756
880
  }
757
881
 
758
882
  if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
759
883
  /* compress remaining input < blockSize */
760
884
  lastBlockCompressed = fromSrcBuffer;
761
- dstPtr += LZ4F_makeBlock(dstPtr, srcPtr, srcEnd - srcPtr,
885
+ dstPtr += LZ4F_makeBlock(dstPtr,
886
+ srcPtr, (size_t)(srcEnd - srcPtr),
762
887
  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
763
- cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
888
+ cctxPtr->cdict,
889
+ cctxPtr->prefs.frameInfo.blockChecksumFlag);
764
890
  srcPtr = srcEnd;
765
891
  }
766
892
 
@@ -786,28 +912,30 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
786
912
  /* some input data left, necessarily < blockSize */
787
913
  if (srcPtr < srcEnd) {
788
914
  /* fill tmp buffer */
789
- size_t const sizeToCopy = srcEnd - srcPtr;
915
+ size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
790
916
  memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
791
917
  cctxPtr->tmpInSize = sizeToCopy;
792
918
  }
793
919
 
794
920
  if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
795
- XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
921
+ (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
796
922
 
797
923
  cctxPtr->totalInSize += srcSize;
798
- return dstPtr - dstStart;
924
+ return (size_t)(dstPtr - dstStart);
799
925
  }
800
926
 
801
927
 
802
928
  /*! LZ4F_flush() :
803
- * Should you need to create compressed data immediately, without waiting for a block to be filled,
804
- * you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext.
805
- * The result of the function is the number of bytes written into dstBuffer
806
- * (it can be zero, this means there was no data left within compressionContext)
929
+ * When compressed data must be sent immediately, without waiting for a block to be filled,
930
+ * invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx.
931
+ * The result of the function is the number of bytes written into dstBuffer.
932
+ * It can be zero, this means there was no data left within LZ4F_cctx.
807
933
  * The function outputs an error code if it fails (can be tested using LZ4F_isError())
808
- * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
934
+ * LZ4F_compressOptions_t* is optional. NULL is a valid argument.
809
935
  */
810
- size_t LZ4F_flush(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t* compressOptionsPtr)
936
+ size_t LZ4F_flush(LZ4F_cctx* cctxPtr,
937
+ void* dstBuffer, size_t dstCapacity,
938
+ const LZ4F_compressOptions_t* compressOptionsPtr)
811
939
  {
812
940
  BYTE* const dstStart = (BYTE*)dstBuffer;
813
941
  BYTE* dstPtr = dstStart;
@@ -815,52 +943,65 @@ size_t LZ4F_flush(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstCapacity, const
815
943
 
816
944
  if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
817
945
  if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
818
- if (dstCapacity < (cctxPtr->tmpInSize + 4)) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); /* +4 : block header(4) */
946
+ if (dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize))
947
+ return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
819
948
  (void)compressOptionsPtr; /* not yet useful */
820
949
 
821
950
  /* select compression function */
822
951
  compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
823
952
 
824
953
  /* compress tmp buffer */
825
- dstPtr += LZ4F_makeBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize,
954
+ dstPtr += LZ4F_makeBlock(dstPtr,
955
+ cctxPtr->tmpIn, cctxPtr->tmpInSize,
826
956
  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
827
- cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
828
- if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;
957
+ cctxPtr->cdict,
958
+ cctxPtr->prefs.frameInfo.blockChecksumFlag);
959
+ assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity));
960
+
961
+ if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)
962
+ cctxPtr->tmpIn += cctxPtr->tmpInSize;
829
963
  cctxPtr->tmpInSize = 0;
830
964
 
831
965
  /* keep tmpIn within limits */
832
966
  if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */
833
- int realDictSize = LZ4F_localSaveDict(cctxPtr);
967
+ int const realDictSize = LZ4F_localSaveDict(cctxPtr);
834
968
  cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
835
969
  }
836
970
 
837
- return dstPtr - dstStart;
971
+ return (size_t)(dstPtr - dstStart);
838
972
  }
839
973
 
840
974
 
841
975
  /*! LZ4F_compressEnd() :
842
- * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
843
- * It will flush whatever data remained within compressionContext (like LZ4_flush())
844
- * but also properly finalize the frame, with an endMark and a checksum.
845
- * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
846
- * The function outputs an error code if it fails (can be tested using LZ4F_isError())
847
- * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
848
- * compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
976
+ * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
977
+ * It will flush whatever data remained within compressionContext (like LZ4_flush())
978
+ * but also properly finalize the frame, with an endMark and an (optional) checksum.
979
+ * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
980
+ * @return: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
981
+ * or an error code if it fails (can be tested using LZ4F_isError())
982
+ * The context can then be used again to compress a new frame, starting with LZ4F_compressBegin().
849
983
  */
850
- size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
984
+ size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,
985
+ void* dstBuffer, size_t dstCapacity,
986
+ const LZ4F_compressOptions_t* compressOptionsPtr)
851
987
  {
852
988
  BYTE* const dstStart = (BYTE*)dstBuffer;
853
989
  BYTE* dstPtr = dstStart;
854
990
 
855
- size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstMaxSize, compressOptionsPtr);
991
+ size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
856
992
  if (LZ4F_isError(flushSize)) return flushSize;
857
993
  dstPtr += flushSize;
858
994
 
995
+ assert(flushSize <= dstCapacity);
996
+ dstCapacity -= flushSize;
997
+
998
+ if (dstCapacity < 4) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
859
999
  LZ4F_writeLE32(dstPtr, 0);
860
- dstPtr+=4; /* endMark */
1000
+ dstPtr += 4; /* endMark */
861
1001
 
862
1002
  if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
863
1003
  U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
1004
+ if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
864
1005
  LZ4F_writeLE32(dstPtr, xxh);
865
1006
  dstPtr+=4; /* content Checksum */
866
1007
  }
@@ -873,7 +1014,7 @@ size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize,
873
1014
  return err0r(LZ4F_ERROR_frameSize_wrong);
874
1015
  }
875
1016
 
876
- return dstPtr - dstStart;
1017
+ return (size_t)(dstPtr - dstStart);
877
1018
  }
878
1019
 
879
1020
 
@@ -887,8 +1028,7 @@ typedef enum {
887
1028
  dstage_getBlockHeader, dstage_storeBlockHeader,
888
1029
  dstage_copyDirect, dstage_getBlockChecksum,
889
1030
  dstage_getCBlock, dstage_storeCBlock,
890
- dstage_decodeCBlock, dstage_decodeCBlock_intoDst,
891
- dstage_decodeCBlock_intoTmp, dstage_flushOut,
1031
+ dstage_flushOut,
892
1032
  dstage_getSuffix, dstage_storeSuffix,
893
1033
  dstage_getSFrameSize, dstage_storeSFrameSize,
894
1034
  dstage_skipSkippable
@@ -924,7 +1064,7 @@ struct LZ4F_dctx_s {
924
1064
  */
925
1065
  LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)
926
1066
  {
927
- LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOCATOR(sizeof(LZ4F_dctx));
1067
+ LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOC_AND_ZERO(sizeof(LZ4F_dctx));
928
1068
  if (dctx==NULL) return err0r(LZ4F_ERROR_GENERIC);
929
1069
 
930
1070
  dctx->version = versionNumber;
@@ -955,31 +1095,6 @@ void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx)
955
1095
  }
956
1096
 
957
1097
 
958
- /*! LZ4F_headerSize() :
959
- * @return : size of frame header
960
- * or an error code, which can be tested using LZ4F_isError()
961
- */
962
- static size_t LZ4F_headerSize(const void* src, size_t srcSize)
963
- {
964
- /* minimal srcSize to determine header size */
965
- if (srcSize < 5) return err0r(LZ4F_ERROR_frameHeader_incomplete);
966
-
967
- /* special case : skippable frames */
968
- if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) return 8;
969
-
970
- /* control magic number */
971
- if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)
972
- return err0r(LZ4F_ERROR_frameType_unknown);
973
-
974
- /* Frame Header Size */
975
- { BYTE const FLG = ((const BYTE*)src)[4];
976
- U32 const contentSizeFlag = (FLG>>3) & _1BIT;
977
- U32 const dictIDFlag = FLG & _1BIT;
978
- return minFHSize + (contentSizeFlag*8) + (dictIDFlag*4);
979
- }
980
- }
981
-
982
-
983
1098
  /*! LZ4F_decodeHeader() :
984
1099
  * input : `src` points at the **beginning of the frame**
985
1100
  * output : set internal values of dctx, such as
@@ -996,7 +1111,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
996
1111
 
997
1112
  /* need to decode header to get frameInfo */
998
1113
  if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
999
- memset(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
1114
+ MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
1000
1115
 
1001
1116
  /* special case : skippable frames */
1002
1117
  if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {
@@ -1031,7 +1146,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1031
1146
  }
1032
1147
 
1033
1148
  /* Frame Header Size */
1034
- frameHeaderSize = minFHSize + (contentSizeFlag*8) + (dictIDFlag*4);
1149
+ frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
1035
1150
 
1036
1151
  if (srcSize < frameHeaderSize) {
1037
1152
  /* not enough input to fully decode frame header */
@@ -1052,6 +1167,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1052
1167
  }
1053
1168
 
1054
1169
  /* check header */
1170
+ assert(frameHeaderSize > 5);
1055
1171
  { BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
1056
1172
  if (HC != srcPtr[frameHeaderSize-1])
1057
1173
  return err0r(LZ4F_ERROR_headerChecksum_invalid);
@@ -1075,6 +1191,34 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1075
1191
  }
1076
1192
 
1077
1193
 
1194
+ /*! LZ4F_headerSize() :
1195
+ * @return : size of frame header
1196
+ * or an error code, which can be tested using LZ4F_isError()
1197
+ */
1198
+ size_t LZ4F_headerSize(const void* src, size_t srcSize)
1199
+ {
1200
+ if (src == NULL) return err0r(LZ4F_ERROR_srcPtr_wrong);
1201
+
1202
+ /* minimal srcSize to determine header size */
1203
+ if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH)
1204
+ return err0r(LZ4F_ERROR_frameHeader_incomplete);
1205
+
1206
+ /* special case : skippable frames */
1207
+ if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
1208
+ return 8;
1209
+
1210
+ /* control magic number */
1211
+ if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)
1212
+ return err0r(LZ4F_ERROR_frameType_unknown);
1213
+
1214
+ /* Frame Header Size */
1215
+ { BYTE const FLG = ((const BYTE*)src)[4];
1216
+ U32 const contentSizeFlag = (FLG>>3) & _1BIT;
1217
+ U32 const dictIDFlag = FLG & _1BIT;
1218
+ return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
1219
+ }
1220
+ }
1221
+
1078
1222
  /*! LZ4F_getFrameInfo() :
1079
1223
  * This function extracts frame parameters (max blockSize, frame checksum, etc.).
1080
1224
  * Usage is optional. Objective is to provide relevant information for allocation purposes.
@@ -1090,10 +1234,12 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1090
1234
  * note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped.
1091
1235
  * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.
1092
1236
  */
1093
- LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, LZ4F_frameInfo_t* frameInfoPtr,
1094
- const void* srcBuffer, size_t* srcSizePtr)
1237
+ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
1238
+ LZ4F_frameInfo_t* frameInfoPtr,
1239
+ const void* srcBuffer, size_t* srcSizePtr)
1095
1240
  {
1096
- if (dctx->dStage > dstage_storeFrameHeader) { /* assumption : dstage_* header enum at beginning of range */
1241
+ LZ4F_STATIC_ASSERT(dstage_getFrameHeader < dstage_storeFrameHeader);
1242
+ if (dctx->dStage > dstage_storeFrameHeader) {
1097
1243
  /* frameInfo already decoded */
1098
1244
  size_t o=0, i=0;
1099
1245
  *srcSizePtr = 0;
@@ -1106,7 +1252,6 @@ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, LZ4F_frameInfo_t* frameInfoP
1106
1252
  *srcSizePtr = 0;
1107
1253
  return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted);
1108
1254
  } else {
1109
- size_t decodeResult;
1110
1255
  size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
1111
1256
  if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
1112
1257
  if (*srcSizePtr < hSize) {
@@ -1114,45 +1259,53 @@ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, LZ4F_frameInfo_t* frameInfoP
1114
1259
  return err0r(LZ4F_ERROR_frameHeader_incomplete);
1115
1260
  }
1116
1261
 
1117
- decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
1118
- if (LZ4F_isError(decodeResult)) {
1119
- *srcSizePtr = 0;
1120
- } else {
1121
- *srcSizePtr = decodeResult;
1122
- decodeResult = BHSize; /* block header size */
1123
- }
1124
- *frameInfoPtr = dctx->frameInfo;
1125
- return decodeResult;
1126
- } }
1262
+ { size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
1263
+ if (LZ4F_isError(decodeResult)) {
1264
+ *srcSizePtr = 0;
1265
+ } else {
1266
+ *srcSizePtr = decodeResult;
1267
+ decodeResult = BHSize; /* block header size */
1268
+ }
1269
+ *frameInfoPtr = dctx->frameInfo;
1270
+ return decodeResult;
1271
+ } } }
1127
1272
  }
1128
1273
 
1129
1274
 
1130
1275
  /* LZ4F_updateDict() :
1131
1276
  * only used for LZ4F_blockLinked mode */
1132
- static void LZ4F_updateDict(LZ4F_dctx* dctx, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
1277
+ static void LZ4F_updateDict(LZ4F_dctx* dctx,
1278
+ const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,
1279
+ unsigned withinTmp)
1133
1280
  {
1134
1281
  if (dctx->dictSize==0)
1135
1282
  dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
1136
1283
 
1137
- if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity */
1284
+ if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity, directly within dstBuffer */
1138
1285
  dctx->dictSize += dstSize;
1139
1286
  return;
1140
1287
  }
1141
1288
 
1142
- if (dstPtr - dstPtr0 + dstSize >= 64 KB) { /* dstBuffer large enough to become dictionary */
1143
- dctx->dict = (const BYTE*)dstPtr0;
1144
- dctx->dictSize = dstPtr - dstPtr0 + dstSize;
1289
+ assert(dstPtr >= dstBufferStart);
1290
+ if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */
1291
+ dctx->dict = (const BYTE*)dstBufferStart;
1292
+ dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize;
1145
1293
  return;
1146
1294
  }
1147
1295
 
1148
- if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) {
1149
- /* assumption : dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart */
1296
+ assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */
1297
+
1298
+ /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOut */
1299
+
1300
+ if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
1301
+ /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */
1302
+ assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);
1150
1303
  dctx->dictSize += dstSize;
1151
1304
  return;
1152
1305
  }
1153
1306
 
1154
1307
  if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
1155
- size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1308
+ size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
1156
1309
  size_t copySize = 64 KB - dctx->tmpOutSize;
1157
1310
  const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1158
1311
  if (dctx->tmpOutSize > 64 KB) copySize = 0;
@@ -1167,7 +1320,7 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx, const BYTE* dstPtr, size_t dstSize,
1167
1320
 
1168
1321
  if (dctx->dict == dctx->tmpOutBuffer) { /* copy dst into tmp to complete dict */
1169
1322
  if (dctx->dictSize + dstSize > dctx->maxBufferSize) { /* tmp buffer not large enough */
1170
- size_t const preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1323
+ size_t const preserveSize = 64 KB - dstSize;
1171
1324
  memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
1172
1325
  dctx->dictSize = preserveSize;
1173
1326
  }
@@ -1177,7 +1330,7 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx, const BYTE* dstPtr, size_t dstSize,
1177
1330
  }
1178
1331
 
1179
1332
  /* join dict & dest into tmp */
1180
- { size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1333
+ { size_t preserveSize = 64 KB - dstSize;
1181
1334
  if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize;
1182
1335
  memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
1183
1336
  memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize);
@@ -1223,7 +1376,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1223
1376
  size_t nextSrcSizeHint = 1;
1224
1377
 
1225
1378
 
1226
- memset(&optionsNull, 0, sizeof(optionsNull));
1379
+ MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
1227
1380
  if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1228
1381
  *srcSizePtr = 0;
1229
1382
  *dstSizePtr = 0;
@@ -1237,14 +1390,14 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1237
1390
 
1238
1391
  case dstage_getFrameHeader:
1239
1392
  if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
1240
- size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, srcEnd-srcPtr); /* will update dStage appropriately */
1393
+ size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */
1241
1394
  if (LZ4F_isError(hSize)) return hSize;
1242
1395
  srcPtr += hSize;
1243
1396
  break;
1244
1397
  }
1245
1398
  dctx->tmpInSize = 0;
1246
1399
  if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */
1247
- dctx->tmpInTarget = minFHSize; /* minimum to attempt decode */
1400
+ dctx->tmpInTarget = minFHSize; /* minimum size to decode header */
1248
1401
  dctx->dStage = dstage_storeFrameHeader;
1249
1402
  /* fall-through */
1250
1403
 
@@ -1265,18 +1418,18 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1265
1418
  break;
1266
1419
 
1267
1420
  case dstage_init:
1268
- if (dctx->frameInfo.contentChecksumFlag) XXH32_reset(&(dctx->xxh), 0);
1421
+ if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);
1269
1422
  /* internal buffers allocation */
1270
1423
  { size_t const bufferNeeded = dctx->maxBlockSize
1271
- + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB);
1424
+ + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0);
1272
1425
  if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
1273
1426
  dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
1274
1427
  FREEMEM(dctx->tmpIn);
1275
- dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize + 4 /* block checksum */);
1428
+ dctx->tmpIn = (BYTE*)ALLOC(dctx->maxBlockSize + BFSize /* block checksum */);
1276
1429
  if (dctx->tmpIn == NULL)
1277
1430
  return err0r(LZ4F_ERROR_allocation_failed);
1278
1431
  FREEMEM(dctx->tmpOutBuffer);
1279
- dctx->tmpOutBuffer= (BYTE*)ALLOCATOR(bufferNeeded);
1432
+ dctx->tmpOutBuffer= (BYTE*)ALLOC(bufferNeeded);
1280
1433
  if (dctx->tmpOutBuffer== NULL)
1281
1434
  return err0r(LZ4F_ERROR_allocation_failed);
1282
1435
  dctx->maxBufferSize = bufferNeeded;
@@ -1319,7 +1472,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1319
1472
 
1320
1473
  /* decode block header */
1321
1474
  { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1322
- size_t const crcSize = dctx->frameInfo.blockChecksumFlag * 4;
1475
+ size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;
1323
1476
  if (nextCBlockSize==0) { /* frameEnd signal, no more block */
1324
1477
  dctx->dStage = dstage_getSuffix;
1325
1478
  break;
@@ -1330,7 +1483,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1330
1483
  /* next block is uncompressed */
1331
1484
  dctx->tmpInTarget = nextCBlockSize;
1332
1485
  if (dctx->frameInfo.blockChecksumFlag) {
1333
- XXH32_reset(&dctx->blockChecksum, 0);
1486
+ (void)XXH32_reset(&dctx->blockChecksum, 0);
1334
1487
  }
1335
1488
  dctx->dStage = dstage_copyDirect;
1336
1489
  break;
@@ -1339,7 +1492,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1339
1492
  dctx->tmpInTarget = nextCBlockSize + crcSize;
1340
1493
  dctx->dStage = dstage_getCBlock;
1341
1494
  if (dstPtr==dstEnd) {
1342
- nextSrcSizeHint = nextCBlockSize + crcSize + BHSize;
1495
+ nextSrcSizeHint = BHSize + nextCBlockSize + crcSize;
1343
1496
  doAnotherStage = 0;
1344
1497
  }
1345
1498
  break;
@@ -1350,10 +1503,10 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1350
1503
  size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
1351
1504
  memcpy(dstPtr, srcPtr, sizeToCopy);
1352
1505
  if (dctx->frameInfo.blockChecksumFlag) {
1353
- XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1506
+ (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1354
1507
  }
1355
1508
  if (dctx->frameInfo.contentChecksumFlag)
1356
- XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1509
+ (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1357
1510
  if (dctx->frameInfo.contentSize)
1358
1511
  dctx->frameRemainingSize -= sizeToCopy;
1359
1512
 
@@ -1373,7 +1526,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1373
1526
  }
1374
1527
  dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
1375
1528
  nextSrcSizeHint = dctx->tmpInTarget +
1376
- + dctx->frameInfo.contentChecksumFlag * 4 /* block checksum */
1529
+ +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1377
1530
  + BHSize /* next header size */;
1378
1531
  doAnotherStage = 0;
1379
1532
  break;
@@ -1401,8 +1554,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1401
1554
  U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
1402
1555
  if (readCRC != calcCRC)
1403
1556
  return err0r(LZ4F_ERROR_blockChecksum_invalid);
1404
- }
1405
- }
1557
+ } }
1406
1558
  dctx->dStage = dstage_getBlockHeader; /* new block */
1407
1559
  break;
1408
1560
 
@@ -1415,9 +1567,8 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1415
1567
  /* input large enough to read full block directly */
1416
1568
  selectedIn = srcPtr;
1417
1569
  srcPtr += dctx->tmpInTarget;
1418
- dctx->dStage = dstage_decodeCBlock;
1419
- break;
1420
1570
 
1571
+ if (0) /* jump over next block */
1421
1572
  case dstage_storeCBlock:
1422
1573
  { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
1423
1574
  size_t const inputLeft = (size_t)(srcEnd-srcPtr);
@@ -1426,51 +1577,54 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1426
1577
  dctx->tmpInSize += sizeToCopy;
1427
1578
  srcPtr += sizeToCopy;
1428
1579
  if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */
1429
- nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize;
1430
- doAnotherStage=0;
1580
+ nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize)
1581
+ + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1582
+ + BHSize /* next header size */;
1583
+ doAnotherStage = 0;
1431
1584
  break;
1432
1585
  }
1433
1586
  selectedIn = dctx->tmpIn;
1434
- dctx->dStage = dstage_decodeCBlock;
1435
1587
  }
1436
- /* fall-through */
1437
1588
 
1438
- /* At this stage, input is large enough to decode a block */
1439
- case dstage_decodeCBlock:
1589
+ /* At this stage, input is large enough to decode a block */
1440
1590
  if (dctx->frameInfo.blockChecksumFlag) {
1441
1591
  dctx->tmpInTarget -= 4;
1592
+ assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */
1442
1593
  { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);
1443
1594
  U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);
1444
1595
  if (readBlockCrc != calcBlockCrc)
1445
1596
  return err0r(LZ4F_ERROR_blockChecksum_invalid);
1446
1597
  } }
1447
- if ((size_t)(dstEnd-dstPtr) < dctx->maxBlockSize) /* not enough place into dst : decode into tmpOut */
1448
- dctx->dStage = dstage_decodeCBlock_intoTmp;
1449
- else
1450
- dctx->dStage = dstage_decodeCBlock_intoDst;
1451
- break;
1452
1598
 
1453
- case dstage_decodeCBlock_intoDst:
1454
- { int const decodedSize = LZ4_decompress_safe_usingDict(
1599
+ if ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize) {
1600
+ const char* dict = (const char*)dctx->dict;
1601
+ size_t dictSize = dctx->dictSize;
1602
+ int decodedSize;
1603
+ if (dict && dictSize > 1 GB) {
1604
+ /* the dictSize param is an int, avoid truncation / sign issues */
1605
+ dict += dictSize - 64 KB;
1606
+ dictSize = 64 KB;
1607
+ }
1608
+ /* enough capacity in `dst` to decompress directly there */
1609
+ decodedSize = LZ4_decompress_safe_usingDict(
1455
1610
  (const char*)selectedIn, (char*)dstPtr,
1456
1611
  (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1457
- (const char*)dctx->dict, (int)dctx->dictSize);
1612
+ dict, (int)dictSize);
1458
1613
  if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
1459
1614
  if (dctx->frameInfo.contentChecksumFlag)
1460
- XXH32_update(&(dctx->xxh), dstPtr, decodedSize);
1615
+ XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize);
1461
1616
  if (dctx->frameInfo.contentSize)
1462
- dctx->frameRemainingSize -= decodedSize;
1617
+ dctx->frameRemainingSize -= (size_t)decodedSize;
1463
1618
 
1464
1619
  /* dictionary management */
1465
1620
  if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1466
- LZ4F_updateDict(dctx, dstPtr, decodedSize, dstStart, 0);
1621
+ LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
1467
1622
 
1468
1623
  dstPtr += decodedSize;
1469
1624
  dctx->dStage = dstage_getBlockHeader;
1470
1625
  break;
1471
1626
  }
1472
1627
 
1473
- case dstage_decodeCBlock_intoTmp:
1474
1628
  /* not enough place into dst : decode into tmpOut */
1475
1629
  /* ensure enough place for tmpOut */
1476
1630
  if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
@@ -1483,21 +1637,28 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1483
1637
  } else { /* dict not within tmp */
1484
1638
  size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);
1485
1639
  dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;
1486
- }
1487
- }
1640
+ } }
1488
1641
 
1489
1642
  /* Decode block */
1490
- { int const decodedSize = LZ4_decompress_safe_usingDict(
1643
+ { const char* dict = (const char*)dctx->dict;
1644
+ size_t dictSize = dctx->dictSize;
1645
+ int decodedSize;
1646
+ if (dict && dictSize > 1 GB) {
1647
+ /* the dictSize param is an int, avoid truncation / sign issues */
1648
+ dict += dictSize - 64 KB;
1649
+ dictSize = 64 KB;
1650
+ }
1651
+ decodedSize = LZ4_decompress_safe_usingDict(
1491
1652
  (const char*)selectedIn, (char*)dctx->tmpOut,
1492
1653
  (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1493
- (const char*)dctx->dict, (int)dctx->dictSize);
1654
+ dict, (int)dictSize);
1494
1655
  if (decodedSize < 0) /* decompression failed */
1495
1656
  return err0r(LZ4F_ERROR_decompressionFailed);
1496
1657
  if (dctx->frameInfo.contentChecksumFlag)
1497
- XXH32_update(&(dctx->xxh), dctx->tmpOut, decodedSize);
1658
+ XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize);
1498
1659
  if (dctx->frameInfo.contentSize)
1499
- dctx->frameRemainingSize -= decodedSize;
1500
- dctx->tmpOutSize = decodedSize;
1660
+ dctx->frameRemainingSize -= (size_t)decodedSize;
1661
+ dctx->tmpOutSize = (size_t)decodedSize;
1501
1662
  dctx->tmpOutStart = 0;
1502
1663
  dctx->dStage = dstage_flushOut;
1503
1664
  }
@@ -1508,8 +1669,8 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1508
1669
  memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
1509
1670
 
1510
1671
  /* dictionary management */
1511
- if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1512
- LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1);
1672
+ if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
1673
+ LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/);
1513
1674
 
1514
1675
  dctx->tmpOutStart += sizeToCopy;
1515
1676
  dstPtr += sizeToCopy;
@@ -1518,8 +1679,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1518
1679
  dctx->dStage = dstage_getBlockHeader; /* get next block */
1519
1680
  break;
1520
1681
  }
1682
+ /* could not flush everything : stop there, just request a block header */
1683
+ doAnotherStage = 0;
1521
1684
  nextSrcSizeHint = BHSize;
1522
- doAnotherStage = 0; /* still some data to flush */
1523
1685
  break;
1524
1686
  }
1525
1687
 
@@ -1556,7 +1718,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1556
1718
  selectedIn = dctx->tmpIn;
1557
1719
  } /* if (dctx->dStage == dstage_storeSuffix) */
1558
1720
 
1559
- /* case dstage_checkSuffix: */ /* no direct call, avoid scan-build warning */
1721
+ /* case dstage_checkSuffix: */ /* no direct entry, avoid initialization risks */
1560
1722
  { U32 const readCRC = LZ4F_readLE32(selectedIn);
1561
1723
  U32 const resultCRC = XXH32_digest(&(dctx->xxh));
1562
1724
  if (readCRC != resultCRC)
@@ -1580,8 +1742,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1580
1742
 
1581
1743
  if (dctx->dStage == dstage_storeSFrameSize)
1582
1744
  case dstage_storeSFrameSize:
1583
- {
1584
- size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
1745
+ { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
1585
1746
  (size_t)(srcEnd - srcPtr) );
1586
1747
  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1587
1748
  srcPtr += sizeToCopy;
@@ -1595,7 +1756,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1595
1756
  selectedIn = dctx->header + 4;
1596
1757
  } /* if (dctx->dStage == dstage_storeSFrameSize) */
1597
1758
 
1598
- /* case dstage_decodeSFrameSize: */ /* no direct access */
1759
+ /* case dstage_decodeSFrameSize: */ /* no direct entry */
1599
1760
  { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
1600
1761
  dctx->frameInfo.contentSize = SFrameSize;
1601
1762
  dctx->tmpInTarget = SFrameSize;
@@ -1614,7 +1775,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1614
1775
  LZ4F_resetDecompressionContext(dctx);
1615
1776
  break;
1616
1777
  }
1617
- }
1778
+ } /* switch (dctx->dStage) */
1618
1779
  } /* while (doAnotherStage) */
1619
1780
 
1620
1781
  /* preserve history within tmp whenever necessary */
@@ -1625,7 +1786,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1625
1786
  && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
1626
1787
  {
1627
1788
  if (dctx->dStage == dstage_flushOut) {
1628
- size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1789
+ size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
1629
1790
  size_t copySize = 64 KB - dctx->tmpOutSize;
1630
1791
  const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1631
1792
  if (dctx->tmpOutSize > 64 KB) copySize = 0;
@@ -1649,8 +1810,8 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1649
1810
  }
1650
1811
  }
1651
1812
 
1652
- *srcSizePtr = (srcPtr - srcStart);
1653
- *dstSizePtr = (dstPtr - dstStart);
1813
+ *srcSizePtr = (size_t)(srcPtr - srcStart);
1814
+ *dstSizePtr = (size_t)(dstPtr - dstStart);
1654
1815
  return nextSrcSizeHint;
1655
1816
  }
1656
1817