summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrzemyslaw Skibinski <inikep@gmail.com>2016-11-04 09:22:32 (GMT)
committerPrzemyslaw Skibinski <inikep@gmail.com>2016-11-04 09:22:32 (GMT)
commit6ebf8859e3a3e4d59117fe88941d6fc25ecba7ba (patch)
tree75c1e64bf9d21575ef0a65ffc81d2306ecc1689d
parent4c496fabaa275f8e082cfc9dda08fdbd0f0844b4 (diff)
parent6d6a3e0fb582be4979404a5e8e368df8b891d686 (diff)
downloadlz4-6ebf8859e3a3e4d59117fe88941d6fc25ecba7ba.zip
lz4-6ebf8859e3a3e4d59117fe88941d6fc25ecba7ba.tar.gz
lz4-6ebf8859e3a3e4d59117fe88941d6fc25ecba7ba.tar.bz2
Merge remote-tracking branch 'refs/remotes/lz4/dev' into dev
-rw-r--r--lib/Makefile4
-rw-r--r--lib/lz4.c25
-rw-r--r--lib/lz4frame.c298
-rw-r--r--lib/lz4frame.h152
-rw-r--r--lib/lz4frame_static.h21
-rw-r--r--lib/lz4hc.c4
-rw-r--r--programs/lz4cli.c2
-rw-r--r--programs/lz4io.c12
-rw-r--r--programs/lz4io.h4
-rw-r--r--tests/.gitignore9
-rw-r--r--tests/Makefile5
11 files changed, 271 insertions, 265 deletions
diff --git a/lib/Makefile b/lib/Makefile
index bd47ee3..8b2cbff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -46,7 +46,9 @@ DESTDIR?=
PREFIX ?= /usr/local
CPPFLAGS= -DXXH_NAMESPACE=LZ4_ -DLZ4_DLL_EXPORT=1
CFLAGS ?= -O3
-CFLAGS += -Wall -Wextra -Wundef -Wshadow -Wcast-align -Wcast-qual -Wstrict-prototypes
+CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
+ -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef \
+ -Wpointer-arith # -Wstrict-aliasing=1
FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
LIBDIR?= $(PREFIX)/lib
diff --git a/lib/lz4.c b/lib/lz4.c
index 5b7d71f..6a6aaf2 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -85,9 +85,10 @@
/*-************************************
-* Includes
+* Dependency
**************************************/
#include "lz4.h"
+/* see also "memory routines" below */
/*-************************************
@@ -99,15 +100,13 @@
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
#else
-# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
-# if defined(__GNUC__) || defined(__clang__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
+# if defined(__GNUC__) || defined(__clang__)
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# elif defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
+# define FORCE_INLINE static inline
# else
# define FORCE_INLINE static
-# endif /* __STDC_VERSION__ */
+# endif
#endif /* _MSC_VER */
/* LZ4_GCC_VERSION is defined into lz4.h */
@@ -134,7 +133,7 @@
/*-************************************
* Basic Types
**************************************/
-#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
@@ -165,6 +164,7 @@ static unsigned LZ4_isLittleEndian(void)
#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
+/* lie to the compiler about data alignment; use with caution */
static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }
static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }
@@ -186,7 +186,7 @@ static size_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uAr
static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
-#else
+#else /* safe and portable access through memcpy() */
static U16 LZ4_read16(const void* memPtr)
{
@@ -242,7 +242,7 @@ static void LZ4_copy8(void* dst, const void* src)
memcpy(dst,src,8);
}
-/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
+/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
{
BYTE* d = (BYTE*)dstPtr;
@@ -354,7 +354,7 @@ static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLi
const BYTE* const pStart = pIn;
while (likely(pIn<pInLimit-(STEPSIZE-1))) {
- size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
+ size_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
pIn += LZ4_NbCommonBytes(diff);
return (unsigned)(pIn - pStart);
@@ -1475,4 +1475,3 @@ int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int origin
}
#endif /* LZ4_COMMONDEFS_ONLY */
-
diff --git a/lib/lz4frame.c b/lib/lz4frame.c
index 6bb76a1..08b7050 100644
--- a/lib/lz4frame.c
+++ b/lib/lz4frame.c
@@ -84,6 +84,7 @@ You can contact the author at :
typedef unsigned long long U64;
#endif
+
/* unoptimized version; solves endianess & alignment issues */
static U32 LZ4F_readLE32 (const void* src)
{
@@ -95,16 +96,18 @@ static U32 LZ4F_readLE32 (const void* src)
return value32;
}
-static void LZ4F_writeLE32 (BYTE* dstPtr, U32 value32)
+static void LZ4F_writeLE32 (void* dst, U32 value32)
{
+ BYTE* const dstPtr = (BYTE*)dst;
dstPtr[0] = (BYTE)value32;
dstPtr[1] = (BYTE)(value32 >> 8);
dstPtr[2] = (BYTE)(value32 >> 16);
dstPtr[3] = (BYTE)(value32 >> 24);
}
-static U64 LZ4F_readLE64 (const BYTE* srcPtr)
+static U64 LZ4F_readLE64 (const void* src)
{
+ const BYTE* const srcPtr = (const BYTE*)src;
U64 value64 = srcPtr[0];
value64 += ((U64)srcPtr[1]<<8);
value64 += ((U64)srcPtr[2]<<16);
@@ -116,8 +119,9 @@ static U64 LZ4F_readLE64 (const BYTE* srcPtr)
return value64;
}
-static void LZ4F_writeLE64 (BYTE* dstPtr, U64 value64)
+static void LZ4F_writeLE64 (void* dst, U64 value64)
{
+ BYTE* const dstPtr = (BYTE*)dst;
dstPtr[0] = (BYTE)value64;
dstPtr[1] = (BYTE)(value64 >> 8);
dstPtr[2] = (BYTE)(value64 >> 16);
@@ -171,28 +175,6 @@ typedef struct LZ4F_cctx_s
U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
} LZ4F_cctx_t;
-typedef struct LZ4F_dctx_s
-{
- LZ4F_frameInfo_t frameInfo;
- U32 version;
- U32 dStage;
- U64 frameRemainingSize;
- size_t maxBlockSize;
- size_t maxBufferSize;
- const BYTE* srcExpect;
- BYTE* tmpIn;
- size_t tmpInSize;
- size_t tmpInTarget;
- BYTE* tmpOutBuffer;
- const BYTE* dict;
- size_t dictSize;
- BYTE* tmpOut;
- size_t tmpOutSize;
- size_t tmpOutStart;
- XXH32_state_t xxh;
- BYTE header[16];
-} LZ4F_dctx_t;
-
/*-************************************
* Error management
@@ -213,6 +195,10 @@ const char* LZ4F_getErrorName(LZ4F_errorCode_t code)
return codeError;
}
+static LZ4F_errorCode_t err0r(LZ4F_errorCodes code) { return (LZ4F_errorCode_t)-(LZ4F_errorCode_t)code; }
+
+unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; }
+
/*-************************************
* Private functions
@@ -223,14 +209,14 @@ static size_t LZ4F_getBlockSize(unsigned blockSizeID)
if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
blockSizeID -= 4;
- if (blockSizeID > 3) return (size_t)-LZ4F_ERROR_maxBlockSize_invalid;
+ if (blockSizeID > 3) return err0r(LZ4F_ERROR_maxBlockSize_invalid);
return blockSizes[blockSizeID];
}
static BYTE LZ4F_headerChecksum (const void* header, size_t length)
{
- U32 xxh = XXH32(header, length, 0);
+ U32 const xxh = XXH32(header, length, 0);
return (BYTE)(xxh >> 8);
}
@@ -281,16 +267,15 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
* The result of the function is the number of bytes written into dstBuffer.
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
*/
-size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
+size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
{
LZ4F_cctx_t cctxI;
LZ4_stream_t lz4ctx;
LZ4F_preferences_t prefs;
LZ4F_compressOptions_t options;
- LZ4F_errorCode_t errorCode;
BYTE* const dstStart = (BYTE*) dstBuffer;
BYTE* dstPtr = dstStart;
- BYTE* const dstEnd = dstStart + dstMaxSize;
+ BYTE* const dstEnd = dstStart + dstCapacity;
memset(&cctxI, 0, sizeof(cctxI)); /* works because no allocation */
memset(&options, 0, sizeof(options));
@@ -317,22 +302,22 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuf
options.stableSrc = 1;
- if (dstMaxSize < LZ4F_compressFrameBound(srcSize, &prefs))
- return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
+ if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs))
+ return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
- errorCode = LZ4F_compressBegin(&cctxI, dstBuffer, dstMaxSize, &prefs); /* write header */
- if (LZ4F_isError(errorCode)) return errorCode;
- dstPtr += errorCode; /* header size */
+ { size_t const headerSize = LZ4F_compressBegin(&cctxI, dstBuffer, dstCapacity, &prefs); /* write header */
+ if (LZ4F_isError(headerSize)) return headerSize;
+ dstPtr += headerSize; /* header size */ }
- errorCode = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);
- if (LZ4F_isError(errorCode)) return errorCode;
- dstPtr += errorCode;
+ { size_t const cSize = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);
+ if (LZ4F_isError(cSize)) return cSize;
+ dstPtr += cSize; }
- errorCode = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
- if (LZ4F_isError(errorCode)) return errorCode;
- dstPtr += errorCode;
+ { size_t const tailSize = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
+ if (LZ4F_isError(tailSize)) return tailSize;
+ dstPtr += tailSize; }
- if (prefs.compressionLevel >= LZ4HC_MIN_CLEVEL) /* no allocation necessary with lz4 fast */
+ if (prefs.compressionLevel >= LZ4HC_MIN_CLEVEL) /* no allocation done with lz4 fast */
FREEMEM(cctxI.lz4CtxPtr);
return (dstPtr - dstStart);
@@ -343,20 +328,18 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuf
* Advanced compression functions
***********************************/
-/* LZ4F_createCompressionContext() :
-* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
-* This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
-* The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
-* The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
-* If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
-* Object can release its memory using LZ4F_freeCompressionContext();
-*/
+/*! LZ4F_createCompressionContext() :
+ * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
+ * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
+ * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
+ * The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
+ * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
+ * Object can release its memory using LZ4F_freeCompressionContext();
+ */
LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
{
- LZ4F_cctx_t* cctxPtr;
-
- cctxPtr = (LZ4F_cctx_t*)ALLOCATOR(sizeof(LZ4F_cctx_t));
- if (cctxPtr==NULL) return (LZ4F_errorCode_t)(-LZ4F_ERROR_allocation_failed);
+ LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOCATOR(sizeof(LZ4F_cctx_t));
+ if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
cctxPtr->version = version;
cctxPtr->cStage = 0; /* Next stage : write header */
@@ -369,7 +352,7 @@ LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_c
LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
{
- LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
+ LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
if (cctxPtr != NULL) { /* null pointers can be safely provided to this function, like free() */
FREEMEM(cctxPtr->lz4CtxPtr);
@@ -382,22 +365,21 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp
/*! LZ4F_compressBegin() :
-* will write the frame header into dstBuffer.
-* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LZ4F_MAXHEADERFRAME_SIZE bytes.
-* The result of the function is the number of bytes written into dstBuffer for the header
-* or an error code (can be tested using LZ4F_isError())
-*/
-size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr)
+ * will write the frame header into dstBuffer.
+ * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LZ4F_MAXHEADERFRAME_SIZE bytes.
+ * @return : number of bytes written into dstBuffer for the header
+ * or an error code (can be tested using LZ4F_isError())
+ */
+size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr)
{
LZ4F_preferences_t prefNull;
- LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
BYTE* const dstStart = (BYTE*)dstBuffer;
BYTE* dstPtr = dstStart;
BYTE* headerStart;
size_t requiredBuffSize;
- if (dstMaxSize < maxFHSize) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
- if (cctxPtr->cStage != 0) return (size_t)-LZ4F_ERROR_GENERIC;
+ if (dstMaxSize < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
+ if (cctxPtr->cStage != 0) return err0r(LZ4F_ERROR_GENERIC);
memset(&prefNull, 0, sizeof(prefNull));
if (preferencesPtr == NULL) preferencesPtr = &prefNull;
cctxPtr->prefs = *preferencesPtr;
@@ -426,7 +408,7 @@ size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* ds
cctxPtr->maxBufferSize = requiredBuffSize;
FREEMEM(cctxPtr->tmpBuff);
cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);
- if (cctxPtr->tmpBuff == NULL) return (size_t)-LZ4F_ERROR_allocation_failed;
+ if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed);
}
cctxPtr->tmpIn = cctxPtr->tmpBuff;
cctxPtr->tmpInSize = 0;
@@ -473,13 +455,13 @@ size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesP
LZ4F_preferences_t prefsNull;
memset(&prefsNull, 0, sizeof(prefsNull));
prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */
- { const LZ4F_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
- LZ4F_blockSizeID_t bid = prefsPtr->frameInfo.blockSizeID;
- size_t blockSize = LZ4F_getBlockSize(bid);
- unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;
- size_t lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;
- size_t blockInfo = 4; /* default, without block CRC option */
- size_t frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
+ { const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
+ LZ4F_blockSizeID_t const bid = prefsPtr->frameInfo.blockSizeID;
+ size_t const blockSize = LZ4F_getBlockSize(bid);
+ unsigned const nbBlocks = (unsigned)(srcSize / blockSize) + 1;
+ size_t const lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;
+ size_t const blockInfo = 4; /* default, without block CRC option */
+ size_t const frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
return (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;;
}
@@ -491,9 +473,8 @@ typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize
static size_t LZ4F_compressBlock(void* dst, const void* src, size_t srcSize, compressFunc_t compress, void* lz4ctx, int level)
{
/* compress one block */
- BYTE* cSizePtr = (BYTE*)dst;
- U32 cSize;
- cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);
+ BYTE* const cSizePtr = (BYTE*)dst;
+ U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);
LZ4F_writeLE32(cSizePtr, cSize);
if (cSize == 0) { /* compression failed */
cSize = (U32)srcSize;
@@ -550,11 +531,10 @@ typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
* The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
*/
-size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr)
+size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr)
{
LZ4F_compressOptions_t cOptionsNull;
- LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
- size_t blockSize = cctxPtr->maxBlockSize;
+ size_t const blockSize = cctxPtr->maxBlockSize;
const BYTE* srcPtr = (const BYTE*)srcBuffer;
const BYTE* const srcEnd = srcPtr + srcSize;
BYTE* const dstStart = (BYTE*)dstBuffer;
@@ -563,8 +543,8 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
compressFunc_t compress;
- if (cctxPtr->cStage != 1) return (size_t)-LZ4F_ERROR_GENERIC;
- if (dstMaxSize < LZ4F_compressBound(srcSize, &(cctxPtr->prefs))) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
+ if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
+ if (dstMaxSize < LZ4F_compressBound(srcSize, &(cctxPtr->prefs))) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
memset(&cOptionsNull, 0, sizeof(cOptionsNull));
if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
@@ -573,7 +553,7 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
/* complete tmp buffer */
if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
- size_t sizeToCopy = blockSize - cctxPtr->tmpInSize;
+ size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
if (sizeToCopy > srcSize) {
/* add src to tmpIn buffer */
memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
@@ -613,7 +593,7 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
cctxPtr->tmpIn = cctxPtr->tmpBuff;
} else {
int realDictSize = LZ4F_localSaveDict(cctxPtr);
- if (realDictSize==0) return (size_t)-LZ4F_ERROR_GENERIC;
+ if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC);
cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
}
}
@@ -629,7 +609,7 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
/* some input data left, necessarily < blockSize */
if (srcPtr < srcEnd) {
/* fill tmp buffer */
- size_t sizeToCopy = srcEnd - srcPtr;
+ size_t const sizeToCopy = srcEnd - srcPtr;
memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
cctxPtr->tmpInSize = sizeToCopy;
}
@@ -650,17 +630,15 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
* The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
*/
-size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
+size_t LZ4F_flush(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
{
- LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
BYTE* const dstStart = (BYTE*)dstBuffer;
BYTE* dstPtr = dstStart;
compressFunc_t compress;
-
if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
- if (cctxPtr->cStage != 1) return (size_t)-LZ4F_ERROR_GENERIC;
- if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall; /* +8 : block header(4) + block checksum(4) */
+ if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
+ if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); /* +8 : block header(4) + block checksum(4) */
(void)compressOptionsPtr; /* not yet useful */
/* select compression function */
@@ -690,22 +668,20 @@ size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer,
* The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
* compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
*/
-size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
+size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
{
- LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
BYTE* const dstStart = (BYTE*)dstBuffer;
BYTE* dstPtr = dstStart;
- size_t errorCode;
- errorCode = LZ4F_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);
- if (LZ4F_isError(errorCode)) return errorCode;
- dstPtr += errorCode;
+ size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstMaxSize, compressOptionsPtr);
+ if (LZ4F_isError(flushSize)) return flushSize;
+ dstPtr += flushSize;
LZ4F_writeLE32(dstPtr, 0);
dstPtr+=4; /* endMark */
if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
- U32 xxh = XXH32_digest(&(cctxPtr->xxh));
+ U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
LZ4F_writeLE32(dstPtr, xxh);
dstPtr+=4; /* content Checksum */
}
@@ -715,7 +691,7 @@ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstB
if (cctxPtr->prefs.frameInfo.contentSize) {
if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
- return (size_t)-LZ4F_ERROR_frameSize_wrong;
+ return err0r(LZ4F_ERROR_frameSize_wrong);
}
return dstPtr - dstStart;
@@ -726,7 +702,26 @@ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstB
* Frame Decompression
*****************************************************/
-/* Resource management */
+struct LZ4F_dctx_s {
+ LZ4F_frameInfo_t frameInfo;
+ U32 version;
+ U32 dStage;
+ U64 frameRemainingSize;
+ size_t maxBlockSize;
+ size_t maxBufferSize;
+ BYTE* tmpIn;
+ size_t tmpInSize;
+ size_t tmpInTarget;
+ BYTE* tmpOutBuffer;
+ const BYTE* dict;
+ size_t dictSize;
+ BYTE* tmpOut;
+ size_t tmpOutSize;
+ size_t tmpOutStart;
+ XXH32_state_t xxh;
+ BYTE header[16];
+}; /* typedef'd to LZ4F_dctx in lz4frame.h */
+
/*! LZ4F_createDecompressionContext() :
* Create a decompressionContext object, which will track all decompression operations.
@@ -734,20 +729,19 @@ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstB
* Object can later be released using LZ4F_freeDecompressionContext().
* @return : if != 0, there was an error during context creation.
*/
-LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_decompressionContext_t* LZ4F_decompressionContextPtr, unsigned versionNumber)
+LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)
{
- LZ4F_dctx_t* const dctxPtr = (LZ4F_dctx_t*)ALLOCATOR(sizeof(LZ4F_dctx_t));
- if (dctxPtr==NULL) return (LZ4F_errorCode_t)-LZ4F_ERROR_GENERIC;
+ LZ4F_dctx* const dctxPtr = (LZ4F_dctx*)ALLOCATOR(sizeof(LZ4F_dctx));
+ if (dctxPtr==NULL) return err0r(LZ4F_ERROR_GENERIC);
dctxPtr->version = versionNumber;
- *LZ4F_decompressionContextPtr = (LZ4F_decompressionContext_t)dctxPtr;
+ *LZ4F_decompressionContextPtr = dctxPtr;
return LZ4F_OK_NoError;
}
-LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t LZ4F_decompressionContext)
+LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* const dctxPtr)
{
LZ4F_errorCode_t result = LZ4F_OK_NoError;
- LZ4F_dctx_t* const dctxPtr = (LZ4F_dctx_t*)LZ4F_decompressionContext;
if (dctxPtr != NULL) { /* can accept NULL input, like free() */
result = (LZ4F_errorCode_t)dctxPtr->dStage;
FREEMEM(dctxPtr->tmpIn);
@@ -758,9 +752,7 @@ LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t LZ4F_
}
-/* ******************************************************************** */
-/* ********************* Decompression ******************************** */
-/* ******************************************************************** */
+/*==--- Streaming Decompression operations ---==*/
typedef enum { dstage_getHeader=0, dstage_storeHeader,
dstage_getCBlockSize, dstage_storeCBlockSize,
@@ -781,13 +773,13 @@ typedef enum { dstage_getHeader=0, dstage_storeHeader,
static size_t LZ4F_headerSize(const void* src, size_t srcSize)
{
/* minimal srcSize to determine header size */
- if (srcSize < 5) return (size_t)-LZ4F_ERROR_frameHeader_incomplete;
+ if (srcSize < 5) return err0r(LZ4F_ERROR_frameHeader_incomplete);
/* special case : skippable frames */
if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) return 8;
/* control magic number */
- if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER) return (size_t)-LZ4F_ERROR_frameType_unknown;
+ if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER) return err0r(LZ4F_ERROR_frameType_unknown);
/* Frame Header Size */
{ BYTE const FLG = ((const BYTE*)src)[4];
@@ -798,29 +790,29 @@ static size_t LZ4F_headerSize(const void* src, size_t srcSize)
/*! LZ4F_decodeHeader() :
- input : `srcVoidPtr` points at the **beginning of the frame**
+ input : `src` points at the **beginning of the frame**
output : set internal values of dctx, such as
dctxPtr->frameInfo and dctxPtr->dStage.
Also allocates internal buffers.
@return : nb Bytes read from srcVoidPtr (necessarily <= srcSize)
or an error code (testable with LZ4F_isError())
*/
-static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)
+static size_t LZ4F_decodeHeader(LZ4F_dctx* dctxPtr, const void* src, size_t srcSize)
{
BYTE FLG, BD, HC;
unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;
size_t bufferNeeded;
size_t frameHeaderSize;
- const BYTE* srcPtr = (const BYTE*)srcVoidPtr;
+ const BYTE* srcPtr = (const BYTE*)src;
/* need to decode header to get frameInfo */
- if (srcSize < minFHSize) return (size_t)-LZ4F_ERROR_frameHeader_incomplete; /* minimal frame header size */
+ if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));
/* special case : skippable frames */
if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {
dctxPtr->frameInfo.frameType = LZ4F_skippableFrame;
- if (srcVoidPtr == (void*)(dctxPtr->header)) {
+ if (src == (void*)(dctxPtr->header)) {
dctxPtr->tmpInSize = srcSize;
dctxPtr->tmpInTarget = 8;
dctxPtr->dStage = dstage_storeSFrameSize;
@@ -832,7 +824,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, si
}
/* control magic number */
- if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return (size_t)-LZ4F_ERROR_frameType_unknown;
+ if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return err0r(LZ4F_ERROR_frameType_unknown);
dctxPtr->frameInfo.frameType = LZ4F_frame;
/* Flags */
@@ -860,16 +852,16 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, si
blockSizeID = (BD>>4) & _3BITS;
/* validate */
- if (version != 1) return (size_t)-LZ4F_ERROR_headerVersion_wrong; /* Version Number, only supported value */
- if (blockChecksumFlag != 0) return (size_t)-LZ4F_ERROR_blockChecksum_unsupported; /* Not supported for the time being */
- if (((FLG>>0)&_2BITS) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bits */
- if (((BD>>7)&_1BIT) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bit */
- if (blockSizeID < 4) return (size_t)-LZ4F_ERROR_maxBlockSize_invalid; /* 4-7 only supported values for the time being */
- if (((BD>>0)&_4BITS) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bits */
+ if (version != 1) return err0r(LZ4F_ERROR_headerVersion_wrong); /* Version Number, only supported value */
+ if (blockChecksumFlag != 0) return err0r(LZ4F_ERROR_blockChecksum_unsupported); /* Not supported for the time being */
+ if (((FLG>>0)&_2BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */
+ if (((BD>>7)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
+ if (blockSizeID < 4) return err0r(LZ4F_ERROR_maxBlockSize_invalid); /* 4-7 only supported values for the time being */
+ if (((BD>>0)&_4BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */
/* check */
HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
- if (HC != srcPtr[frameHeaderSize-1]) return (size_t)-LZ4F_ERROR_headerChecksum_invalid; /* Bad header checksum error */
+ if (HC != srcPtr[frameHeaderSize-1]) return err0r(LZ4F_ERROR_headerChecksum_invalid); /* Bad header checksum error */
/* save */
dctxPtr->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;
@@ -889,9 +881,9 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, si
FREEMEM(dctxPtr->tmpOutBuffer);
dctxPtr->maxBufferSize = bufferNeeded;
dctxPtr->tmpIn = (BYTE*)ALLOCATOR(dctxPtr->maxBlockSize);
- if (dctxPtr->tmpIn == NULL) return (size_t)-LZ4F_ERROR_GENERIC;
+ if (dctxPtr->tmpIn == NULL) return err0r(LZ4F_ERROR_GENERIC);
dctxPtr->tmpOutBuffer= (BYTE*)ALLOCATOR(dctxPtr->maxBufferSize);
- if (dctxPtr->tmpOutBuffer== NULL) return (size_t)-LZ4F_ERROR_GENERIC;
+ if (dctxPtr->tmpOutBuffer== NULL) return err0r(LZ4F_ERROR_GENERIC);
}
dctxPtr->tmpInSize = 0;
dctxPtr->tmpInTarget = 0;
@@ -908,35 +900,32 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, si
/*! LZ4F_getFrameInfo() :
-* Decodes frame header information, such as blockSize.
-* It is optional : you could start by calling directly LZ4F_decompress() instead.
-* The objective is to extract header information without starting decompression, typically for allocation purposes.
+* Decodes frame header information, such as blockSize. Usage is optional.
+* The objective is to extract header information before receiving decompressed data, typically for allocation purposes.
* LZ4F_getFrameInfo() can also be used *after* starting decompression, on a valid LZ4F_decompressionContext_t.
-* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
-* You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)
+* The number of bytes consumed from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
+* Decompression must resume from where it stopped (srcBuffer + *srcSizePtr)
* @return : hint of the better `srcSize` to use for next call to LZ4F_decompress,
* or an error code which can be tested using LZ4F_isError().
*/
-LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t dCtx, LZ4F_frameInfo_t* frameInfoPtr,
+LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctxPtr, LZ4F_frameInfo_t* frameInfoPtr,
const void* srcBuffer, size_t* srcSizePtr)
{
- LZ4F_dctx_t* dctxPtr = (LZ4F_dctx_t*)dCtx;
-
if (dctxPtr->dStage > dstage_storeHeader) { /* note : requires dstage_* header related to be at beginning of enum */
/* frameInfo already decoded */
size_t o=0, i=0;
*srcSizePtr = 0;
*frameInfoPtr = dctxPtr->frameInfo;
- return LZ4F_decompress(dCtx, NULL, &o, NULL, &i, NULL); /* returns : recommended nb of bytes for LZ4F_decompress() */
+ return LZ4F_decompress(dctxPtr, NULL, &o, NULL, &i, NULL); /* returns : recommended nb of bytes for LZ4F_decompress() */
} else {
size_t nextSrcSize, o=0;
size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
- if (*srcSizePtr < hSize) { *srcSizePtr=0; return (size_t)-LZ4F_ERROR_frameHeader_incomplete; }
+ if (*srcSizePtr < hSize) { *srcSizePtr=0; return err0r(LZ4F_ERROR_frameHeader_incomplete); }
*srcSizePtr = hSize;
- nextSrcSize = LZ4F_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);
- if (dctxPtr->dStage <= dstage_storeHeader) return (size_t)-LZ4F_ERROR_frameHeader_incomplete; /* should not happen, already checked */
+ nextSrcSize = LZ4F_decompress(dctxPtr, NULL, &o, srcBuffer, srcSizePtr, NULL);
+ if (dctxPtr->dStage <= dstage_storeHeader) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* should not happen, already checked */
*frameInfoPtr = dctxPtr->frameInfo;
return nextSrcSize;
}
@@ -951,7 +940,7 @@ static int LZ4F_decompress_safe (const char* source, char* dest, int compressedS
}
-static void LZ4F_updateDict(LZ4F_dctx_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
+static void LZ4F_updateDict(LZ4F_dctx* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
{
if (dctxPtr->dictSize==0)
dctxPtr->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
@@ -1012,27 +1001,26 @@ static void LZ4F_updateDict(LZ4F_dctx_t* dctxPtr, const BYTE* dstPtr, size_t dst
/*! LZ4F_decompress() :
* Call this function repetitively to regenerate data compressed within srcBuffer.
-* The function will attempt to decode *srcSizePtr from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
+* The function will attempt to decode up to *srcSizePtr bytes from srcBuffer, into dstBuffer of capacity *dstSizePtr.
*
* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
*
* The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
* If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.
-* You will have to call it again, continuing from where it stopped.
+* Remaining data will have to be presented again in a subsequent invocation.
*
* The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
* Basically, it's the size of the current (or remaining) compressed block + header of next block.
* Respecting the hint provides some boost to performance, since it allows less buffer shuffling.
-* Note that this is just a hint, you can always provide any srcSize you want.
-* When a frame is fully decoded, the function result will be 0.
-* If decompression failed, function result is an error code which can be tested using LZ4F_isError().
+* Note that this is just a hint, it's always possible to any srcSize value.
+* When a frame is fully decoded, @return will be 0.
+* If decompression failed, @return is an error code which can be tested using LZ4F_isError().
*/
-size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
+size_t LZ4F_decompress(LZ4F_dctx* dctxPtr,
void* dstBuffer, size_t* dstSizePtr,
const void* srcBuffer, size_t* srcSizePtr,
const LZ4F_decompressOptions_t* decompressOptionsPtr)
{
- LZ4F_dctx_t* dctxPtr = (LZ4F_dctx_t*)decompressionContext;
LZ4F_decompressOptions_t optionsNull;
const BYTE* const srcStart = (const BYTE*)srcBuffer;
const BYTE* const srcEnd = srcStart + *srcSizePtr;
@@ -1050,11 +1038,6 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
*srcSizePtr = 0;
*dstSizePtr = 0;
- /* expect to continue decoding src buffer where it left previously */
- if (dctxPtr->srcExpect != NULL) {
- if (srcStart != dctxPtr->srcExpect) return (size_t)-LZ4F_ERROR_srcPtr_wrong;
- }
-
/* programmed as a state machine */
while (doAnotherStage) {
@@ -1103,8 +1086,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
if (dctxPtr->dStage == dstage_storeCBlockSize) /* can be skipped */
case dstage_storeCBlockSize:
- {
- size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;
+ { size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;
if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
srcPtr += sizeToCopy;
@@ -1123,7 +1105,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
dctxPtr->dStage = dstage_getSuffix;
break;
}
- if (nextCBlockSize > dctxPtr->maxBlockSize) return (size_t)-LZ4F_ERROR_GENERIC; /* invalid cBlockSize */
+ if (nextCBlockSize > dctxPtr->maxBlockSize) return err0r(LZ4F_ERROR_GENERIC); /* invalid cBlockSize */
dctxPtr->tmpInTarget = nextCBlockSize;
if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
dctxPtr->dStage = dstage_copyDirect;
@@ -1205,7 +1187,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
decoder = LZ4F_decompress_safe;
decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
- if (decodedSize < 0) return (size_t)-LZ4F_ERROR_GENERIC; /* decompression failed */
+ if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);
if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;
@@ -1245,7 +1227,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
/* Decode */
decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
- if (decodedSize < 0) return (size_t)-LZ4F_ERROR_decompressionFailed; /* decompression failed */
+ if (decodedSize < 0) return err0r(LZ4F_ERROR_decompressionFailed); /* decompression failed */
if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);
if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;
dctxPtr->tmpOutSize = decodedSize;
@@ -1278,7 +1260,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
case dstage_getSuffix:
{ size_t const suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;
- if (dctxPtr->frameRemainingSize) return (size_t)-LZ4F_ERROR_frameSize_wrong; /* incorrect frame size decoded */
+ if (dctxPtr->frameRemainingSize) return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
if (suffixSize == 0) { /* frame completed */
nextSrcSizeHint = 0;
dctxPtr->dStage = dstage_getHeader;
@@ -1313,7 +1295,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
/* case dstage_checkSuffix: */ /* no direct call, to avoid scan-build warning */
{ U32 const readCRC = LZ4F_readLE32(selectedIn);
U32 const resultCRC = XXH32_digest(&(dctxPtr->xxh));
- if (readCRC != resultCRC) return (size_t)-LZ4F_ERROR_contentChecksum_invalid;
+ if (readCRC != resultCRC) return err0r(LZ4F_ERROR_contentChecksum_invalid);
nextSrcSizeHint = 0;
dctxPtr->dStage = dstage_getHeader;
doAnotherStage = 0;
@@ -1400,12 +1382,6 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
}
}
- /* require function to be called again from position where it stopped */
- if (srcPtr<srcEnd)
- dctxPtr->srcExpect = srcPtr;
- else
- dctxPtr->srcExpect = NULL;
-
*srcSizePtr = (srcPtr - srcStart);
*dstSizePtr = (dstPtr - dstStart);
return nextSrcSizeHint;
diff --git a/lib/lz4frame.h b/lib/lz4frame.h
index 79164b8..63abc60 100644
--- a/lib/lz4frame.h
+++ b/lib/lz4frame.h
@@ -34,18 +34,19 @@
/* LZ4F is a stand-alone API to create LZ4-compressed frames
* conformant with specification v1.5.1.
- * All related operations, including memory management, are handled internally by the library.
- * You don't need lz4.h when using lz4frame.h.
+ * It also offers streaming capabilities.
+ * lz4.h is not required when using lz4frame.h.
* */
-#pragma once
+#ifndef LZ4F_H_09782039843
+#define LZ4F_H_09782039843
#if defined (__cplusplus)
extern "C" {
#endif
/*-************************************
-* Includes
+* Dependency
**************************************/
#include <stddef.h> /* size_t */
@@ -78,7 +79,7 @@ LZ4FLIB_API const char* LZ4F_getErrorName(LZ4F_errorCode_t code); /* return er
/*-************************************
* Frame compression types
**************************************/
-//#define LZ4F_DISABLE_OBSOLETE_ENUMS
+/* #define LZ4F_DISABLE_OBSOLETE_ENUMS */ /* uncomment to disable obsolete enums */
#ifndef LZ4F_DISABLE_OBSOLETE_ENUMS
# define LZ4F_OBSOLETE_ENUM(x) ,x
#else
@@ -136,7 +137,7 @@ typedef struct {
typedef struct {
LZ4F_frameInfo_t frameInfo;
int compressionLevel; /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */
- unsigned autoFlush; /* 1 == always flush (reduce need for tmp buffer) */
+ unsigned autoFlush; /* 1 == always flush (reduce usage of tmp buffer) */
unsigned reserved[4]; /* must be zero for forward compatibility */
} LZ4F_preferences_t;
@@ -144,55 +145,60 @@ typedef struct {
/*-*********************************
* Simple compression function
***********************************/
+/*!LZ4F_compressFrameBound() :
+ * Returns the maximum possible size of a frame given srcSize content and preferences.
+ */
LZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
/*!LZ4F_compressFrame() :
* Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.5.1
- * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
- * You can get the minimum value of dstMaxSize by using LZ4F_compressFrameBound()
- * If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode)
+ * An important rule is that dstBuffer MUST be large enough (dstCapacity) to store the result in worst case situation.
+ * This value is supplied by LZ4F_compressFrameBound().
+ * If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode).
* The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
- * The result of the function is the number of bytes written into dstBuffer.
- * The function outputs an error code if it fails (can be tested using LZ4F_isError())
+ * @return : number of bytes written into dstBuffer.
+ * or an error code if it fails (can be tested using LZ4F_isError())
*/
-LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
+LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
/*-***********************************
* Advanced compression functions
*************************************/
-typedef struct LZ4F_cctx_s* LZ4F_compressionContext_t; /* must be aligned on 8-bytes */
+typedef struct LZ4F_cctx_s LZ4F_cctx; /* incomplete type */
+typedef LZ4F_cctx* LZ4F_compressionContext_t; /* for compatibility with previous API version */
typedef struct {
- unsigned stableSrc; /* 1 == src content will remain available on future calls to LZ4F_compress(); avoid saving src content within tmp buffer as future dictionary */
+ unsigned stableSrc; /* 1 == src content remain present on future calls to LZ4F_compress(); avoid saving src content within tmp buffer as future dictionary */
unsigned reserved[3];
} LZ4F_compressOptions_t;
/* Resource Management */
#define LZ4F_VERSION 100
-LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* cctxPtr, unsigned version);
-LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t cctx);
+LZ4FLIB_API unsigned LZ4F_getVersion(void);
+LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version);
+LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx);
/* LZ4F_createCompressionContext() :
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
* This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
- * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
- * The function will provide a pointer to a fully allocated LZ4F_compressionContext_t object.
- * If the result LZ4F_errorCode_t is not zero, there was an error during context creation.
+ * The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL.
+ * The function will provide a pointer to a fully allocated LZ4F_cctx object.
+ * If @return != zero, there was an error during context creation.
* Object can release its memory using LZ4F_freeCompressionContext();
*/
/* Compression */
-LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* prefsPtr);
+LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_preferences_t* prefsPtr);
/* LZ4F_compressBegin() :
* will write the frame header into dstBuffer.
- * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
- * The LZ4F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.
- * The result of the function is the number of bytes written into dstBuffer for the header
- * or an error code (can be tested using LZ4F_isError())
+ * dstBuffer must be large enough to accommodate a header. Maximum header size is 15 bytes.
+ * `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default.
+ * @return : number of bytes written into dstBuffer for the header
+ * or an error code (which can be tested using LZ4F_isError())
*/
LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);
@@ -203,46 +209,45 @@ LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t*
* This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)
*/
-LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* cOptPtr);
-/* LZ4F_compressUpdate()
+LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* cOptPtr);
+/* LZ4F_compressUpdate() :
* LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
- * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
- * You can get the minimum value of dstMaxSize by using LZ4F_compressBound().
+ * An important rule is that dstBuffer MUST be large enough (dstCapacity) to ensure compression completion even in worst case.
+ * This value is provided by using LZ4F_compressBound().
* If this condition is not respected, LZ4F_compress() will fail (result is an errorCode).
- * LZ4F_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
- * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
- * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
- * The function outputs an error code if it fails (can be tested using LZ4F_isError())
+ * LZ4F_compressUpdate() doesn't guarantee error recovery. When an error occurs, compression context must be freed or resized.
+ * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.
+ * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).
+ * or an error code if it fails (which can be tested using LZ4F_isError())
*/
-LZ4FLIB_API size_t LZ4F_flush(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* cOptPtr);
-/* LZ4F_flush()
- * Should you need to generate compressed data immediately, without waiting for the current block to be filled,
- * you can call LZ4_flush(), which will immediately compress any remaining data buffered within cctx.
- * Note that dstMaxSize must be large enough to ensure the operation will be successful.
- * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
- * The result of the function is the number of bytes written into dstBuffer
- * (it can be zero, this means there was no data left within cctx)
- * The function outputs an error code if it fails (can be tested using LZ4F_isError())
+LZ4FLIB_API size_t LZ4F_flush(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t* cOptPtr);
+/* LZ4F_flush() :
+ * When data must be generated and sent immediately, without waiting for a block to be completely filled,
+ * it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx.
+ * `dstCapacity` must be large enough to ensure the operation will be successful.
+ * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.
+ * @return : number of bytes written into dstBuffer (it can be zero, which means there was no data stored within cctx)
+ * or an error code if it fails (which can be tested using LZ4F_isError())
*/
-LZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* cOptPtr);
-/* LZ4F_compressEnd()
- * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
- * It will flush whatever data remained within compressionContext (like LZ4_flush())
- * but also properly finalize the frame, with an endMark and a checksum.
- * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)
- * The function outputs an error code if it fails (can be tested using LZ4F_isError())
- * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
- * A successful call to LZ4F_compressEnd() makes cctx available again for next compression task.
+LZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_cctx* cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* cOptPtr);
+/* LZ4F_compressEnd() :
+ * To properly finish the compressed frame, invoke LZ4F_compressEnd().
+ * It will flush whatever data remained within `cctx` (like LZ4_flush())
+ * and properly finalize the frame, with an endMark and a checksum.
+ * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.
+ * @return : number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)
+ * or an error code if it fails (which can be tested using LZ4F_isError())
+ * A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task.
*/
/*-*********************************
* Decompression functions
***********************************/
-
-typedef struct LZ4F_dctx_s* LZ4F_decompressionContext_t; /* must be aligned on 8-bytes */
+typedef struct LZ4F_dctx_s LZ4F_dctx; /* incomplete type */
+typedef LZ4F_dctx* LZ4F_decompressionContext_t; /* compatibility with previous API versions */
typedef struct {
unsigned stableDst; /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */
@@ -261,8 +266,8 @@ typedef struct {
* The result of LZ4F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
* That is, it should be == 0 if decompression has been completed fully and correctly.
*/
-LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_decompressionContext_t* dctxPtr, unsigned version);
-LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t dctx);
+LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version);
+LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx);
/*====== Decompression ======*/
@@ -270,44 +275,43 @@ LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionCon
/*!LZ4F_getFrameInfo() :
* This function decodes frame header information (such as max blockSize, frame checksum, etc.).
* Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.
- * A header size is variable and can be from 7 to 15 bytes. It's also possible to input more bytes than that.
- * The number of bytes read from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
- * (note that LZ4F_getFrameInfo() can also be used anytime *after* starting decompression, in this case 0 input byte is enough)
+ * A header size is variable and can length from 7 to 15 bytes. It's possible to provide more input bytes than that.
+ * The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
+ * Decompression must resume from this point (srcBuffer + *srcSizePtr).
+ * Note that LZ4F_getFrameInfo() can also be used anytime *after* decompression is started, in which case 0 input byte can be enough.
* Frame header info is *copied into* an already allocated LZ4F_frameInfo_t structure.
- * The function result is an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
- * or an error code which can be tested using LZ4F_isError()
- * (typically, when there is not enough src bytes to fully decode the frame header)
- * Decompression is expected to resume from where it stopped (srcBuffer + *srcSizePtr)
+ * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
+ * or an error code which can be tested using LZ4F_isError()
+ * (typically, when there is not enough src bytes to fully decode the frame header)
*/
-LZ4FLIB_API size_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t dctx,
+LZ4FLIB_API size_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
LZ4F_frameInfo_t* frameInfoPtr,
const void* srcBuffer, size_t* srcSizePtr);
/*!LZ4F_decompress() :
- * Call this function repetitively to regenerate data compressed within srcBuffer.
- * The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
+ * Call this function repetitively to regenerate data compressed within `srcBuffer`.
+ * The function will attempt to decode up to *srcSizePtr bytes from srcBuffer, into dstBuffer of capacity *dstSizePtr.
*
* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
*
* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
- * If number of bytes read is < number of bytes provided, then decompression operation is not completed.
+ * Number of bytes read can be < number of bytes provided, meaning there is some more data to decode.
* It typically happens when dstBuffer is not large enough to contain all decoded data.
- * LZ4F_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)
- * The function will check this condition, and refuse to continue if it is not respected.
+ * Remaining data will have to be presented again in a subsequent invocation.
*
- * `dstBuffer` is expected to be flushed between each call to the function, its content will be overwritten.
- * `dst` arguments can be changed at will at each consecutive call to the function.
+ * `dstBuffer` content is expected to be flushed between each invocation, as its content will be overwritten.
+ * `dstBuffer` can be changed at will between each consecutive function invocation.
*
- * The function result is an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call.
+ * @return is an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call.
* Schematically, it's the size of the current (or remaining) compressed block + header of next block.
* Respecting the hint provides some boost to performance, since it does skip intermediate buffers.
* This is just a hint though, it's always possible to provide any srcSize.
- * When a frame is fully decoded, the function result will be 0 (no more data expected).
- * If decompression failed, function result is an error code, which can be tested using LZ4F_isError().
+ * When a frame is fully decoded, @return will be 0 (no more data expected).
+ * If decompression failed, @return is an error code, which can be tested using LZ4F_isError().
*
* After a frame is fully decoded, dctx can be used again to decompress another frame.
*/
-LZ4FLIB_API size_t LZ4F_decompress(LZ4F_decompressionContext_t dctx,
+LZ4FLIB_API size_t LZ4F_decompress(LZ4F_dctx* dctx,
void* dstBuffer, size_t* dstSizePtr,
const void* srcBuffer, size_t* srcSizePtr,
const LZ4F_decompressOptions_t* dOptPtr);
@@ -317,3 +321,5 @@ LZ4FLIB_API size_t LZ4F_decompress(LZ4F_decompressionContext_t dctx,
#if defined (__cplusplus)
}
#endif
+
+#endif /* LZ4F_H_09782039843 */
diff --git a/lib/lz4frame_static.h b/lib/lz4frame_static.h
index 79e481c..fab3def 100644
--- a/lib/lz4frame_static.h
+++ b/lib/lz4frame_static.h
@@ -33,27 +33,24 @@
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
-#pragma once
+#ifndef LZ4FRAME_STATIC_H_0398209384
+#define LZ4FRAME_STATIC_H_0398209384
#if defined (__cplusplus)
extern "C" {
#endif
/* lz4frame_static.h should be used solely in the context of static linking.
- * It contains definitions which may still change overtime.
+ * It contains definitions which are not stable and may change in the future.
* Never use it in the context of DLL linking.
* */
-/**************************************
-* Includes
-**************************************/
+/* --- Dependency --- */
#include "lz4frame.h"
-/**************************************
- * Error management
- * ************************************/
+/* --- Error List --- */
#define LZ4F_LIST_ERRORS(ITEM) \
ITEM(OK_NoError) ITEM(ERROR_GENERIC) \
ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \
@@ -67,11 +64,11 @@ extern "C" {
ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \
ITEM(ERROR_maxCode)
-//#define LZ4F_DISABLE_OLD_ENUMS
+//#define LZ4F_DISABLE_OLD_ENUMS /* uncomment to disable deprecated enums */
#ifndef LZ4F_DISABLE_OLD_ENUMS
-#define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM, ENUM = LZ4F_##ENUM,
+# define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM, ENUM = LZ4F_##ENUM,
#else
-#define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM,
+# define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM,
#endif
typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM) } LZ4F_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
@@ -79,3 +76,5 @@ typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM) } LZ4F_errorCodes; /* enum
#if defined (__cplusplus)
}
#endif
+
+#endif /* LZ4FRAME_STATIC_H_0398209384 */
diff --git a/lib/lz4hc.c b/lib/lz4hc.c
index a1d1a55..f109622 100644
--- a/lib/lz4hc.c
+++ b/lib/lz4hc.c
@@ -108,7 +108,7 @@ typedef struct
* Local Macros
**************************************/
#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
-//#define DELTANEXTU16(p) chainTable[(p) & MAXD_MASK] /* flexible, MAXD dependent */
+/* #define DELTANEXTU16(p) chainTable[(p) & MAXD_MASK] */ /* flexible, MAXD dependent */
#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */
static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
@@ -252,7 +252,7 @@ FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
}
}
} else {
- const BYTE* matchPtr = dictBase + matchIndex;
+ const BYTE* const matchPtr = dictBase + matchIndex;
if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
size_t mlt;
int back=0;
diff --git a/programs/lz4cli.c b/programs/lz4cli.c
index 7cf035e..a6f4b4e 100644
--- a/programs/lz4cli.c
+++ b/programs/lz4cli.c
@@ -393,7 +393,7 @@ int main(int argc, const char** argv)
case 'c': forceStdout=1; output_filename=stdoutmark; displayLevel=1; break;
/* Test integrity */
- case 't': decode=1; LZ4IO_setOverwrite(1); output_filename=nulmark; break;
+ case 't': decode=1; LZ4IO_setTestMode(1); output_filename=nulmark; break;
/* Overwrite */
case 'f': LZ4IO_setOverwrite(1); break;
diff --git a/programs/lz4io.c b/programs/lz4io.c
index f2d7b51..2f64561 100644
--- a/programs/lz4io.c
+++ b/programs/lz4io.c
@@ -136,6 +136,7 @@ static clock_t g_time = 0;
* Local Parameters
**************************************/
static int g_overwrite = 1;
+static int g_testMode = 0;
static int g_blockSizeId = LZ4IO_BLOCKSIZEID_DEFAULT;
static int g_blockChecksum = 0;
static int g_streamChecksum = 1;
@@ -184,6 +185,13 @@ int LZ4IO_setOverwrite(int yes)
return g_overwrite;
}
+/* Default setting : testMode = 0; return : testMode (0/1) */
+int LZ4IO_setTestMode(int yes)
+{
+ g_testMode = (yes!=0);
+ return g_testMode;
+}
+
/* blockSizeID : valid values : 4-5-6-7 */
int LZ4IO_setBlockSizeID(int bsid)
{
@@ -283,7 +291,7 @@ static int LZ4IO_getFiles(const char* input_filename, const char* output_filenam
} else {
/* Check if destination file already exists */
*pfoutput=0;
- if (output_filename != nulmark) *pfoutput = fopen( output_filename, "rb" );
+ if (strcmp(output_filename, nulmark)) *pfoutput = fopen( output_filename, "rb" );
if (*pfoutput!=0) {
fclose(*pfoutput);
if (!g_overwrite) {
@@ -908,7 +916,7 @@ static unsigned long long selectDecoder(dRess_t ress, FILE* finput, FILE* foutpu
EXTENDED_FORMAT; /* macro extension for custom formats */
default:
if (nbCalls == 1) { /* just started */
- if (g_overwrite)
+ if (!g_testMode && g_overwrite)
return LZ4IO_passThrough(finput, foutput, MNstore);
EXM_THROW(44,"Unrecognized header : file cannot be decoded"); /* Wrong magic number at the beginning of 1st stream */
}
diff --git a/programs/lz4io.h b/programs/lz4io.h
index 4f0e02a..bf076ee 100644
--- a/programs/lz4io.h
+++ b/programs/lz4io.h
@@ -63,6 +63,10 @@ int LZ4IO_decompressMultipleFilenames(const char** inFileNamesTable, int ifntSiz
return : overwrite mode (0/1) */
int LZ4IO_setOverwrite(int yes);
+/* Default setting : testMode = 0;
+ return : testMode (0/1) */
+int LZ4IO_setTestMode(int yes);
+
/* blockSizeID : valid values : 4-5-6-7
return : -1 if error, blockSize if OK */
int LZ4IO_setBlockSizeID(int blockSizeID);
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 0000000..8861e67
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1,9 @@
+
+# test build artefacts
+datagen
+frametest
+frametest32
+fullbench
+fullbench32
+fuzzer
+fuzzer32
diff --git a/tests/Makefile b/tests/Makefile
index d7a195a..0c44b21 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -217,7 +217,10 @@ test-lz4-basic: lz4 datagen
test-lz4: lz4 datagen test-lz4-basic test-lz4-multiple test-lz4-sparse test-lz4-contentSize test-lz4-frame-concatenation
@echo "\n ---- test pass-through ----"
- ./datagen | $(PRGDIR)/lz4 -tf
+ ./datagen | $(PRGDIR)/lz4 -t && false || true
+ ./datagen | $(PRGDIR)/lz4 -tf && false || true
+ ./datagen | $(PRGDIR)/lz4 -d > $(VOID) && false || true
+ ./datagen | $(PRGDIR)/lz4 -df > $(VOID)
test-lz4c: lz4c datagen
@echo "\n ---- test lz4c version ----"