lz4-hs 0.1.5.0 → 0.1.5.1
raw patch · 8 files changed
+735/−525 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- cbits/lz4.c +326/−229
- cbits/lz4.h +80/−70
- cbits/lz4frame.c +93/−54
- cbits/lz4frame.h +22/−14
- cbits/lz4hc.c +192/−115
- cbits/lz4hc.h +15/−40
- lz4-hs.cabal +3/−3
CHANGELOG.md view
@@ -1,5 +1,9 @@ # lz4 +## 0.1.5.1++ * Upgrade to lz4 1.9.3 under the hood+ ## 0.1.5.0 * Export single-threaded block compression functions
cbits/lz4.c view
@@ -45,10 +45,16 @@ #endif /*- * ACCELERATION_DEFAULT :+ * LZ4_ACCELERATION_DEFAULT : * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 */-#define ACCELERATION_DEFAULT 1+#define LZ4_ACCELERATION_DEFAULT 1+/*+ * LZ4_ACCELERATION_MAX :+ * Any "acceleration" value higher than this threshold+ * get treated as LZ4_ACCELERATION_MAX instead (fix #876)+ */+#define LZ4_ACCELERATION_MAX 65537 /*-************************************@@ -82,6 +88,7 @@ * Define this parameter if your target system or compiler does not support hardware bit count */ #if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */+# undef LZ4_FORCE_SW_BITCOUNT /* avoid double def */ # define LZ4_FORCE_SW_BITCOUNT #endif @@ -114,10 +121,9 @@ /*-************************************ * Compiler Options **************************************/-#ifdef _MSC_VER /* Visual Studio */-# include <intrin.h>-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */-# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */+#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */+# include <intrin.h> /* only present in VS2005+ */+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ #endif /* _MSC_VER */ #ifndef LZ4_FORCE_INLINE@@ -136,7 +142,7 @@ # endif /* _MSC_VER */ #endif /* LZ4_FORCE_INLINE */ -/* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE+/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8, * together with a simple 8-byte copy loop as a fall-back path. * However, this optimization hurts the decompression speed by >30%,@@ -151,11 +157,11 @@ * of LZ4_wildCopy8 does not affect the compression speed. */ #if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__)-# define LZ4_FORCE_O2_GCC_PPC64LE __attribute__((optimize("O2")))-# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE __attribute__((optimize("O2"))) LZ4_FORCE_INLINE+# define LZ4_FORCE_O2 __attribute__((optimize("O2")))+# undef LZ4_FORCE_INLINE+# define LZ4_FORCE_INLINE static __inline __attribute__((optimize("O2"),always_inline)) #else-# define LZ4_FORCE_O2_GCC_PPC64LE-# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static+# define LZ4_FORCE_O2 #endif #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)@@ -171,14 +177,33 @@ #define unlikely(expr) expect((expr) != 0, 0) #endif +/* Should the alignment test prove unreliable, for some reason,+ * it can be disabled by setting LZ4_ALIGN_TEST to 0 */+#ifndef LZ4_ALIGN_TEST /* can be externally provided */+# define LZ4_ALIGN_TEST 1+#endif + /*-************************************ * Memory routines **************************************/-#include <stdlib.h> /* malloc, calloc, free */-#define ALLOC(s) malloc(s)-#define ALLOC_AND_ZERO(s) calloc(1,s)-#define FREEMEM(p) free(p)+#ifdef LZ4_USER_MEMORY_FUNCTIONS+/* memory management functions can be customized by user project.+ * Below functions must exist somewhere in the Project+ * and be available at link time */+void* LZ4_malloc(size_t s);+void* LZ4_calloc(size_t n, size_t s);+void LZ4_free(void* p);+# define ALLOC(s) LZ4_malloc(s)+# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s)+# define FREEMEM(p) LZ4_free(p)+#else+# include <stdlib.h> /* malloc, calloc, free */+# define ALLOC(s) malloc(s)+# define ALLOC_AND_ZERO(s) calloc(1,s)+# define FREEMEM(p) free(p)+#endif+ #include <string.h> /* memset, memcpy */ #define MEM_INIT(p,v,s) memset((p),(v),(s)) @@ -225,21 +250,27 @@ #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) # include <stdio.h>-static int g_debuglog_enable = 1;-# define DEBUGLOG(l, ...) { \- if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \- fprintf(stderr, __FILE__ ": "); \- fprintf(stderr, __VA_ARGS__); \- fprintf(stderr, " \n"); \- } }+ static int g_debuglog_enable = 1;+# define DEBUGLOG(l, ...) { \+ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \+ fprintf(stderr, __FILE__ ": "); \+ fprintf(stderr, __VA_ARGS__); \+ fprintf(stderr, " \n"); \+ } } #else-# define DEBUGLOG(l, ...) {} /* disabled */+# define DEBUGLOG(l, ...) {} /* disabled */ #endif +static int LZ4_isAligned(const void* ptr, size_t alignment)+{+ return ((size_t)ptr & (alignment -1)) == 0;+} + /*-************************************ * Types **************************************/+#include <limits.h> #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # include <stdint.h> typedef uint8_t BYTE;@@ -249,6 +280,9 @@ typedef uint64_t U64; typedef uintptr_t uptrval; #else+# if UINT_MAX != 4294967295UL+# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4"+# endif typedef unsigned char BYTE; typedef unsigned short U16; typedef unsigned int U32;@@ -273,6 +307,21 @@ /*-************************************ * Reading and writing into memory **************************************/++/**+ * LZ4 relies on memcpy with a constant size being inlined. In freestanding+ * environments, the compiler can't assume the implementation of memcpy() is+ * standard compliant, so it can't apply its specialized memcpy() inlining+ * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze+ * memcpy() as if it were standard compliant, so it can inline it in freestanding+ * environments. This is needed when decompressing the Linux Kernel, for example.+ */+#if defined(__GNUC__) && (__GNUC__ >= 4)+#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)+#else+#define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)+#endif+ static unsigned LZ4_isLittleEndian(void) { const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */@@ -307,27 +356,27 @@ static U16 LZ4_read16(const void* memPtr) {- U16 val; memcpy(&val, memPtr, sizeof(val)); return val;+ U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; } static U32 LZ4_read32(const void* memPtr) {- U32 val; memcpy(&val, memPtr, sizeof(val)); return val;+ U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; } static reg_t LZ4_read_ARCH(const void* memPtr) {- reg_t val; memcpy(&val, memPtr, sizeof(val)); return val;+ reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; } static void LZ4_write16(void* memPtr, U16 value) {- memcpy(memPtr, &value, sizeof(value));+ LZ4_memcpy(memPtr, &value, sizeof(value)); } static void LZ4_write32(void* memPtr, U32 value) {- memcpy(memPtr, &value, sizeof(value));+ LZ4_memcpy(memPtr, &value, sizeof(value)); } #endif /* LZ4_FORCE_MEMORY_ACCESS */@@ -355,14 +404,14 @@ } /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */-LZ4_FORCE_O2_INLINE_GCC_PPC64LE+LZ4_FORCE_INLINE void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; BYTE* const e = (BYTE*)dstEnd; - do { memcpy(d,s,8); d+=8; s+=8; } while (d<e);+ do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d<e); } static const unsigned inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};@@ -370,12 +419,12 @@ #ifndef LZ4_FAST_DEC_LOOP-# if defined(__i386__) || defined(__x86_64__)+# if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64 # define LZ4_FAST_DEC_LOOP 1 # elif defined(__aarch64__) && !defined(__clang__) /* On aarch64, we disable this optimization for clang because on certain- * mobile chipsets and clang, it reduces performance. For more information- * refer to https://github.com/lz4/lz4/pull/707. */+ * mobile chipsets, performance is reduced with clang. For information+ * refer to https://github.com/lz4/lz4/pull/707 */ # define LZ4_FAST_DEC_LOOP 1 # else # define LZ4_FAST_DEC_LOOP 0@@ -384,20 +433,22 @@ #if LZ4_FAST_DEC_LOOP -LZ4_FORCE_O2_INLINE_GCC_PPC64LE void+LZ4_FORCE_INLINE void LZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) {+ assert(srcPtr + offset == dstPtr); if (offset < 8) {+ LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */ dstPtr[0] = srcPtr[0]; dstPtr[1] = srcPtr[1]; dstPtr[2] = srcPtr[2]; dstPtr[3] = srcPtr[3]; srcPtr += inc32table[offset];- memcpy(dstPtr+4, srcPtr, 4);+ LZ4_memcpy(dstPtr+4, srcPtr, 4); srcPtr -= dec64table[offset]; dstPtr += 8; } else {- memcpy(dstPtr, srcPtr, 8);+ LZ4_memcpy(dstPtr, srcPtr, 8); dstPtr += 8; srcPtr += 8; }@@ -408,49 +459,48 @@ /* customized variant of memcpy, which can overwrite up to 32 bytes beyond dstEnd * this version copies two times 16 bytes (instead of one time 32 bytes) * because it must be compatible with offsets >= 16. */-LZ4_FORCE_O2_INLINE_GCC_PPC64LE void+LZ4_FORCE_INLINE void LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; BYTE* const e = (BYTE*)dstEnd; - do { memcpy(d,s,16); memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e);+ do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e); } /* LZ4_memcpy_using_offset() presumes : * - dstEnd >= dstPtr + MINMATCH * - there is at least 8 bytes available to write after dstEnd */-LZ4_FORCE_O2_INLINE_GCC_PPC64LE void+LZ4_FORCE_INLINE void LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) { BYTE v[8]; assert(dstEnd >= dstPtr + MINMATCH);- LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */ switch(offset) { case 1:- memset(v, *srcPtr, 8);+ MEM_INIT(v, *srcPtr, 8); break; case 2:- memcpy(v, srcPtr, 2);- memcpy(&v[2], srcPtr, 2);- memcpy(&v[4], &v[0], 4);+ LZ4_memcpy(v, srcPtr, 2);+ LZ4_memcpy(&v[2], srcPtr, 2);+ LZ4_memcpy(&v[4], v, 4); break; case 4:- memcpy(v, srcPtr, 4);- memcpy(&v[4], srcPtr, 4);+ LZ4_memcpy(v, srcPtr, 4);+ LZ4_memcpy(&v[4], srcPtr, 4); break; default: LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset); return; } - memcpy(dstPtr, v, 8);+ LZ4_memcpy(dstPtr, v, 8); dstPtr += 8; while (dstPtr < dstEnd) {- memcpy(dstPtr, v, 8);+ LZ4_memcpy(dstPtr, v, 8); dstPtr += 8; } }@@ -462,75 +512,92 @@ **************************************/ static unsigned LZ4_NbCommonBytes (reg_t val) {+ assert(val != 0); if (LZ4_isLittleEndian()) {- if (sizeof(val)==8) {-# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)+ if (sizeof(val) == 8) {+# if defined(_MSC_VER) && (_MSC_VER >= 1800) && defined(_M_AMD64) && !defined(LZ4_FORCE_SW_BITCOUNT)+ /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */+ return (unsigned)_tzcnt_u64(val) >> 3;+# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0;- _BitScanForward64( &r, (U64)val );- return (int)(r>>3);-# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)+ _BitScanForward64(&r, (U64)val);+ return (unsigned)r >> 3;+# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_ctzll((U64)val) >> 3; # else- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,- 0, 3, 1, 3, 1, 4, 2, 7,- 0, 2, 3, 6, 1, 5, 3, 5,- 1, 3, 4, 4, 2, 5, 6, 7,- 7, 0, 1, 2, 3, 3, 4, 6,- 2, 6, 5, 5, 3, 4, 5, 6,- 7, 1, 2, 4, 6, 4, 4, 5,- 7, 2, 6, 5, 7, 6, 7, 7 };- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];+ const U64 m = 0x0101010101010101ULL;+ val ^= val - 1;+ return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56); # endif } else /* 32 bits */ {-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)+# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r;- _BitScanForward( &r, (U32)val );- return (int)(r>>3);-# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)+ _BitScanForward(&r, (U32)val);+ return (unsigned)r >> 3;+# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_ctz((U32)val) >> 3; # else- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,- 3, 2, 2, 1, 3, 2, 0, 1,- 3, 3, 1, 2, 2, 2, 2, 0,- 3, 1, 2, 0, 1, 0, 1, 1 };- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];+ const U32 m = 0x01010101;+ return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24; # endif } } else /* Big Endian CPU */ {- if (sizeof(val)==8) { /* 64-bits */-# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)- unsigned long r = 0;- _BitScanReverse64( &r, val );- return (unsigned)(r>>3);-# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)+ if (sizeof(val)==8) {+# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_clzll((U64)val) >> 3; # else+#if 1+ /* this method is probably faster,+ * but adds a 128 bytes lookup table */+ static const unsigned char ctz7_tab[128] = {+ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ };+ U64 const mask = 0x0101010101010101ULL;+ U64 const t = (((val >> 8) - mask) | val) & mask;+ return ctz7_tab[(t * 0x0080402010080402ULL) >> 57];+#else+ /* this method doesn't consume memory space like the previous one,+ * but it contains several branches,+ * that may end up slowing execution */ static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits.- Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.- Note that this code path is never triggered in 32-bits mode. */+ Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.+ Note that this code path is never triggered in 32-bits mode. */ unsigned r; if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; } if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } r += (!val); return r;+#endif # endif } else /* 32 bits */ {-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)- unsigned long r = 0;- _BitScanReverse( &r, (unsigned long)val );- return (unsigned)(r>>3);-# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)+# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_clz((U32)val) >> 3; # else- unsigned r;- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }- r += (!val);- return r;+ val >>= 8;+ val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |+ (val + 0x00FF0000)) >> 24;+ return (unsigned)val ^ 3; # endif } } } + #define STEPSIZE sizeof(reg_t) LZ4_FORCE_INLINE unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)@@ -605,7 +672,7 @@ int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }-int LZ4_sizeofState() { return LZ4_STREAMSIZE; }+int LZ4_sizeofState(void) { return LZ4_STREAMSIZE; } /*-************************************@@ -628,7 +695,7 @@ /*-****************************** * Compression functions ********************************/-static U32 LZ4_hash4(U32 sequence, tableType_t const tableType)+LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType) { if (tableType == byU16) return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));@@ -636,7 +703,7 @@ return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); } -static U32 LZ4_hash5(U64 sequence, tableType_t const tableType)+LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType) { const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; if (LZ4_isLittleEndian()) {@@ -654,7 +721,7 @@ return LZ4_hash4(LZ4_read32(p), tableType); } -static void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)+LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType) { switch (tableType) {@@ -666,7 +733,7 @@ } } -static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)+LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType) { switch (tableType) {@@ -678,7 +745,7 @@ } } -static void LZ4_putPositionOnHash(const BYTE* p, U32 h,+LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) {@@ -703,7 +770,7 @@ * Assumption 1 : only valid if tableType == byU32 or byU16. * Assumption 2 : h is presumed valid (within limits of hash table) */-static U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)+LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType) { LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2); if (tableType == byU32) {@@ -739,22 +806,13 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx, const int inputSize, const tableType_t tableType) {- /* If compression failed during the previous step, then the context- * is marked as dirty, therefore, it has to be fully reset.- */- if (cctx->dirty) {- DEBUGLOG(5, "LZ4_prepareTable: Full reset for %p", cctx);- MEM_INIT(cctx, 0, sizeof(LZ4_stream_t_internal));- return;- }- /* If the table hasn't been used, it's guaranteed to be zeroed out, and is * therefore safe to use no matter what mode we're in. Otherwise, we figure * out if it's safe to leave as is or whether it needs to be reset. */- if (cctx->tableType != clearedTable) {+ if ((tableType_t)cctx->tableType != clearedTable) { assert(inputSize >= 0);- if (cctx->tableType != tableType+ if ((tableType_t)cctx->tableType != tableType || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU) || ((tableType == byU32) && cctx->currentOffset > 1 GB) || tableType == byPtr@@ -763,7 +821,7 @@ DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx); MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE); cctx->currentOffset = 0;- cctx->tableType = clearedTable;+ cctx->tableType = (U32)clearedTable; } else { DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)"); }@@ -785,8 +843,12 @@ } /** LZ4_compress_generic() :- inlined, to ensure branches are decided at compilation time */-LZ4_FORCE_INLINE int LZ4_compress_generic(+ * inlined, to ensure branches are decided at compilation time.+ * Presumed already validated at this stage:+ * - source != NULL+ * - inputSize > 0+ */+LZ4_FORCE_INLINE int LZ4_compress_generic_validated( LZ4_stream_t_internal* const cctx, const char* const source, char* const dest,@@ -815,7 +877,7 @@ int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */- const BYTE* const dictEnd = dictionary + dictSize;+ const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary; const BYTE* anchor = (const BYTE*) source; const BYTE* const iend = ip + inputSize; const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;@@ -823,7 +885,7 @@ /* the dictCtx currentOffset is indexed on the start of the dictionary, * while a dictionary in the current context precedes the currentOffset */- const BYTE* dictBase = (dictDirective == usingDictCtx) ?+ const BYTE* dictBase = !dictionary ? NULL : (dictDirective == usingDictCtx) ? dictionary + dictSize - dictCtx->currentOffset : dictionary + dictSize - startIndex; @@ -833,11 +895,11 @@ U32 offset = 0; U32 forwardH; - DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType);+ DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType);+ assert(ip != NULL); /* If init conditions are not met, we don't have to mark stream * as having dirty context, since no action was taken yet */ if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */- if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported inputSize, too large (or negative) */ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */ if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */ assert(acceleration >= 1);@@ -854,7 +916,7 @@ cctx->dictSize += (U32)inputSize; } cctx->currentOffset += (U32)inputSize;- cctx->tableType = (U16)tableType;+ cctx->tableType = (U32)tableType; if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ @@ -1147,13 +1209,14 @@ if (outputDirective == fillOutput) { /* adapt lastRun to fill 'dst' */ assert(olimit >= op);- lastRun = (size_t)(olimit-op) - 1;- lastRun -= (lastRun+240)/255;+ lastRun = (size_t)(olimit-op) - 1/*token*/;+ lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/ } else { assert(outputDirective == limitedOutput); return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ } }+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun); if (lastRun >= RUN_MASK) { size_t accumulator = lastRun - RUN_MASK; *op++ = RUN_MASK << ML_BITS;@@ -1162,7 +1225,7 @@ } else { *op++ = (BYTE)(lastRun<<ML_BITS); }- memcpy(op, anchor, lastRun);+ LZ4_memcpy(op, anchor, lastRun); ip = anchor + lastRun; op += lastRun; }@@ -1170,18 +1233,60 @@ if (outputDirective == fillOutput) { *inputConsumed = (int) (((const char*)ip)-source); }- DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, (int)(((char*)op) - dest)); result = (int)(((char*)op) - dest); assert(result > 0);+ DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result); return result; } +/** LZ4_compress_generic() :+ * inlined, to ensure branches are decided at compilation time;+ * takes care of src == (NULL, 0)+ * and forward the rest to LZ4_compress_generic_validated */+LZ4_FORCE_INLINE int LZ4_compress_generic(+ LZ4_stream_t_internal* const cctx,+ const char* const src,+ char* const dst,+ const int srcSize,+ int *inputConsumed, /* only written when outputDirective == fillOutput */+ const int dstCapacity,+ const limitedOutput_directive outputDirective,+ const tableType_t tableType,+ const dict_directive dictDirective,+ const dictIssue_directive dictIssue,+ const int acceleration)+{+ DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i",+ srcSize, dstCapacity); + if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */+ if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */+ if (outputDirective != notLimited && dstCapacity <= 0) return 0; /* no output, can't write anything */+ DEBUGLOG(5, "Generating an empty block");+ assert(outputDirective == notLimited || dstCapacity >= 1);+ assert(dst != NULL);+ dst[0] = 0;+ if (outputDirective == fillOutput) {+ assert (inputConsumed != NULL);+ *inputConsumed = 0;+ }+ return 1;+ }+ assert(src != NULL);++ return LZ4_compress_generic_validated(cctx, src, dst, srcSize,+ inputConsumed, /* only written into if outputDirective == fillOutput */+ dstCapacity, outputDirective,+ tableType, dictDirective, dictIssue, acceleration);+}++ int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; assert(ctx != NULL);- if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) { return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration);@@ -1211,7 +1316,8 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) { LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;- if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; if (dstCapacity >= LZ4_compressBound(srcSize)) { if (srcSize < LZ4_64Klimit) {@@ -1270,22 +1376,6 @@ } -/* hidden debug function */-/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */-int LZ4_compress_fast_force(const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)-{- LZ4_stream_t ctx;- LZ4_initStream(&ctx, sizeof(ctx));-- if (srcSize < LZ4_64Klimit) {- return LZ4_compress_generic(&ctx.internal_donotuse, src, dst, srcSize, NULL, dstCapacity, limitedOutput, byU16, noDict, noDictIssue, acceleration);- } else {- tableType_t const addrMode = (sizeof(void*) > 4) ? byU32 : byPtr;- return LZ4_compress_generic(&ctx.internal_donotuse, src, dst, srcSize, NULL, dstCapacity, limitedOutput, addrMode, noDict, noDictIssue, acceleration);- }-}-- /* Note!: This function leaves the stream in an unclean/broken state! * It is not safe to subsequently use the same state with a _fastReset() or * _continue() call without resetting it. */@@ -1340,27 +1430,23 @@ return lz4s; } -#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :- it reports an aligment of 8-bytes,- while actually aligning LZ4_stream_t on 4 bytes. */ static size_t LZ4_stream_t_alignment(void) {- struct { char c; LZ4_stream_t t; } t_a;- return sizeof(t_a) - sizeof(t_a.t);-}+#if LZ4_ALIGN_TEST+ typedef struct { char c; LZ4_stream_t t; } t_a;+ return sizeof(t_a) - sizeof(LZ4_stream_t);+#else+ return 1; /* effectively disabled */ #endif+} LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) { DEBUGLOG(5, "LZ4_initStream"); if (buffer == NULL) { return NULL; } if (size < sizeof(LZ4_stream_t)) { return NULL; }-#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :- it reports an aligment of 8-bytes,- while actually aligning LZ4_stream_t on 4 bytes. */- if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) { return NULL; } /* alignment check */-#endif- MEM_INIT(buffer, 0, sizeof(LZ4_stream_t));+ if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL;+ MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal)); return (LZ4_stream_t*)buffer; } @@ -1369,7 +1455,7 @@ void LZ4_resetStream (LZ4_stream_t* LZ4_stream) { DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream);- MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));+ MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal)); } void LZ4_resetStream_fast(LZ4_stream_t* ctx) {@@ -1418,7 +1504,7 @@ base = dictEnd - dict->currentOffset; dict->dictionary = p; dict->dictSize = (U32)(dictEnd - p);- dict->tableType = tableType;+ dict->tableType = (U32)tableType; while (p <= dictEnd-HASH_UNIT) { LZ4_putPosition(p, dict->hashTable, tableType, base);@@ -1436,12 +1522,6 @@ workingStream, dictionaryStream, dictCtx != NULL ? dictCtx->dictSize : 0); - /* Calling LZ4_resetStream_fast() here makes sure that changes will not be- * erased by subsequent calls to LZ4_resetStream_fast() in case stream was- * marked as having dirty context, e.g. requiring full reset.- */- LZ4_resetStream_fast(workingStream);- if (dictCtx != NULL) { /* If the current offset is zero, we will never look in the * external dictionary context, since there is no value a table@@ -1493,9 +1573,9 @@ DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i)", inputSize); - if (streamPtr->dirty) { return 0; } /* Uninitialized structure detected */ LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */- if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; /* invalidate tiny dictionaries */ if ( (streamPtr->dictSize-1 < 4-1) /* intentional underflow */@@ -1538,7 +1618,7 @@ * cost to copy the dictionary's tables into the active context, * so that the compression loop is only looking into one table. */- memcpy(streamPtr, streamPtr->dictCtx, sizeof(LZ4_stream_t));+ LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr)); result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); } else { result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);@@ -1593,7 +1673,9 @@ if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */ if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; } - memmove(safeBuffer, previousDictEnd - dictSize, dictSize);+ if (safeBuffer == NULL) assert(dictSize == 0);+ if (dictSize > 0)+ memmove(safeBuffer, previousDictEnd - dictSize, dictSize); dict->dictionary = (const BYTE*)safeBuffer; dict->dictSize = (U32)dictSize;@@ -1623,25 +1705,27 @@ */ typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error; LZ4_FORCE_INLINE unsigned-read_variable_length(const BYTE**ip, const BYTE* lencheck, int loop_check, int initial_check, variable_length_error* error)+read_variable_length(const BYTE**ip, const BYTE* lencheck,+ int loop_check, int initial_check,+ variable_length_error* error) {- unsigned length = 0;- unsigned s;- if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */- *error = initial_error;- return length;- }- do {- s = **ip;- (*ip)++;- length += s;- if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */- *error = loop_error;- return length;+ U32 length = 0;+ U32 s;+ if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */+ *error = initial_error;+ return length; }- } while (s==255);+ do {+ s = **ip;+ (*ip)++;+ length += s;+ if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */+ *error = loop_error;+ return length;+ }+ } while (s==255); - return length;+ return length; } /*! LZ4_decompress_generic() :@@ -1722,7 +1806,7 @@ /* decode literal length */ if (length == RUN_MASK) { variable_length_error error = ok;- length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);+ length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error); if (error == initial_error) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */@@ -1746,12 +1830,12 @@ /* We don't need to check oend, since we check it once for each loop below */ if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; } /* Literals can only be 14, but hope compilers optimize if we copy by a register size */- memcpy(op, ip, 16);+ LZ4_memcpy(op, ip, 16); } else { /* LZ4_decompress_fast() */ /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : * it doesn't know input length, and relies on end-of-block properties */- memcpy(op, ip, 8);- if (length > 8) { memcpy(op+8, ip+8, 8); }+ LZ4_memcpy(op, ip, 8);+ if (length > 8) { LZ4_memcpy(op+8, ip+8, 8); } } ip += length; op = cpy; }@@ -1765,10 +1849,10 @@ length = token & ML_MASK; if (length == ML_MASK) {- variable_length_error error = ok;- if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */- length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);- if (error != ok) { goto _output_error; }+ variable_length_error error = ok;+ if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */+ length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);+ if (error != ok) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */ length += MINMATCH; if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {@@ -1787,19 +1871,20 @@ assert(match <= op); assert(op + 18 <= oend); - memcpy(op, match, 8);- memcpy(op+8, match+8, 8);- memcpy(op+16, match+16, 2);+ LZ4_memcpy(op, match, 8);+ LZ4_memcpy(op+8, match+8, 8);+ LZ4_memcpy(op+16, match+16, 2); op += length; continue; } } } - if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */+ if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ /* match starting within external dictionary */ if ((dict==usingExtDict) && (match < lowPrefix)) { if (unlikely(op+length > oend-LASTLITERALS)) { if (partialDecoding) {- length = MIN(length, (size_t)(oend-op)); /* reach end of buffer */+ DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd");+ length = MIN(length, (size_t)(oend-op)); } else { goto _output_error; /* end-of-block condition violated */ } }@@ -1812,14 +1897,14 @@ /* match stretches into both external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix - match); size_t const restSize = length - copySize;- memcpy(op, dictEnd - copySize, copySize);+ LZ4_memcpy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) { *op++ = *copyFrom++; } } else {- memcpy(op, lowPrefix, restSize);+ LZ4_memcpy(op, lowPrefix, restSize); op += restSize; } } continue;@@ -1860,7 +1945,7 @@ /* strictly "less than" on input, to re-enter the loop with at least one byte */ && likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend)) ) { /* Copy the literals */- memcpy(op, ip, endOnInput ? 16 : 8);+ LZ4_memcpy(op, ip, endOnInput ? 16 : 8); op += length; ip += length; /* The second stage: prepare for match copying, decode full info.@@ -1875,9 +1960,9 @@ && (offset >= 8) && (dict==withPrefix64k || match >= lowPrefix) ) { /* Copy the match. */- memcpy(op + 0, match + 0, 8);- memcpy(op + 8, match + 8, 8);- memcpy(op +16, match +16, 2);+ LZ4_memcpy(op + 0, match + 0, 8);+ LZ4_memcpy(op + 8, match + 8, 8);+ LZ4_memcpy(op +16, match +16, 2); op += length + MINMATCH; /* Both stages worked, load the next token. */ continue;@@ -1891,7 +1976,7 @@ /* decode literal length */ if (length == RUN_MASK) { variable_length_error error = ok;- length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);+ length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error); if (error == initial_error) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */@@ -1907,29 +1992,34 @@ || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) { /* We've either hit the input parsing restriction or the output parsing restriction.- * If we've hit the input parsing condition then this must be the last sequence.- * If we've hit the output parsing condition then we are either using partialDecoding- * or we've hit the output parsing condition.+ * In the normal scenario, decoding a full block, it must be the last sequence,+ * otherwise it's an error (invalid input or dimensions).+ * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow. */ if (partialDecoding) { /* Since we are partial decoding we may be in this block because of the output parsing * restriction, which is not valid since the output buffer is allowed to be undersized. */ assert(endOnInput);- /* If we're in this block because of the input parsing condition, then we must be on the- * last sequence (or invalid), so we must check that we exactly consume the input.+ DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end")+ DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length);+ DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op));+ DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip));+ /* Finishing in the middle of a literals segment,+ * due to lack of input. */- if ((ip+length>iend-(2+1+LASTLITERALS)) && (ip+length != iend)) { goto _output_error; }- assert(ip+length <= iend);- /* We are finishing in the middle of a literals segment.- * Break after the copy.+ if (ip+length > iend) {+ length = (size_t)(iend-ip);+ cpy = op + length;+ }+ /* Finishing in the middle of a literals segment,+ * due to lack of output space. */ if (cpy > oend) { cpy = oend; assert(op<=oend); length = (size_t)(oend-op); }- assert(ip+length <= iend); } else { /* We must be on the last sequence because of the parsing limitations so check * that we exactly regenerate the original size (must be exact when !endOnInput).@@ -1938,16 +2028,22 @@ /* We must be on the last sequence (or invalid) because of the parsing limitations * so check that we exactly consume the input and don't overrun the output buffer. */- if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) { goto _output_error; }+ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) {+ DEBUGLOG(6, "should have been last run of literals")+ DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend);+ DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);+ goto _output_error;+ } }- memmove(op, ip, length); /* supports overlapping memory regions, which only matters for in-place decompression scenarios */+ memmove(op, ip, length); /* supports overlapping memory regions; only matters for in-place decompression scenarios */ ip += length; op += length;- /* Necessarily EOF when !partialDecoding. When partialDecoding- * it is EOF if we've either filled the output buffer or hit- * the input parsing restriction.+ /* Necessarily EOF when !partialDecoding.+ * When partialDecoding, it is EOF if we've either+ * filled the output buffer or+ * can't proceed with reading an offset for following match. */- if (!partialDecoding || (cpy == oend) || (ip == iend)) {+ if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) { break; } } else {@@ -1965,7 +2061,7 @@ _copy_match: if (length == ML_MASK) { variable_length_error error = ok;- length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);+ length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error); if (error != ok) goto _output_error; if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ }@@ -1990,14 +2086,14 @@ /* match stretches into both external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix - match); size_t const restSize = length - copySize;- memcpy(op, dictEnd - copySize, copySize);+ LZ4_memcpy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; } else {- memcpy(op, lowPrefix, restSize);+ LZ4_memcpy(op, lowPrefix, restSize); op += restSize; } } continue;@@ -2016,7 +2112,7 @@ if (matchEnd > op) { /* overlap copy */ while (op < copyEnd) { *op++ = *match++; } } else {- memcpy(op, match, mlen);+ LZ4_memcpy(op, match, mlen); } op = copyEnd; if (op == oend) { break; }@@ -2030,10 +2126,10 @@ op[2] = match[2]; op[3] = match[3]; match += inc32table[offset];- memcpy(op+4, match, 4);+ LZ4_memcpy(op+4, match, 4); match -= dec64table[offset]; } else {- memcpy(op, match, 8);+ LZ4_memcpy(op, match, 8); match += 8; } op += 8;@@ -2048,7 +2144,7 @@ } while (op < cpy) { *op++ = *match++; } } else {- memcpy(op, match, 8);+ LZ4_memcpy(op, match, 8); if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } } op = cpy; /* wildcopy correction */@@ -2056,6 +2152,7 @@ /* end of decoding */ if (endOnInput) {+ DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst)); return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ } else { return (int) (((const char*)ip)-src); /* Nb of input bytes read */@@ -2070,7 +2167,7 @@ /*===== Instantiate the API decoding functions. =====*/ -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,@@ -2078,7 +2175,7 @@ (BYTE*)dest, NULL, 0); } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity) { dstCapacity = MIN(targetOutputSize, dstCapacity);@@ -2087,7 +2184,7 @@ noDict, (BYTE*)dst, NULL, 0); } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_fast(const char* source, char* dest, int originalSize) { return LZ4_decompress_generic(source, dest, 0, originalSize,@@ -2097,7 +2194,7 @@ /*===== Instantiate a few more decoding cases, used more than once. =====*/ -LZ4_FORCE_O2_GCC_PPC64LE /* Exported, an obsolete API function. */+LZ4_FORCE_O2 /* Exported, an obsolete API function. */ int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,@@ -2113,7 +2210,7 @@ return LZ4_decompress_fast(source, dest, originalSize); } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize, size_t prefixSize) {@@ -2122,7 +2219,7 @@ (BYTE*)dest-prefixSize, NULL, 0); } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const void* dictStart, size_t dictSize)@@ -2132,7 +2229,7 @@ (BYTE*)dest, (const BYTE*)dictStart, dictSize); } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize, const void* dictStart, size_t dictSize) {@@ -2221,7 +2318,7 @@ If it's not possible, save the relevant part of decoded data into a safe buffer, and indicate where it stands using LZ4_setStreamDecode() */-LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) { LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;@@ -2261,7 +2358,7 @@ return result; } -LZ4_FORCE_O2_GCC_PPC64LE+LZ4_FORCE_O2 int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) { LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;@@ -2374,7 +2471,7 @@ /* Obsolete Streaming functions */ -int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }+int LZ4_sizeofStreamState(void) { return LZ4_STREAMSIZE; } int LZ4_resetStreamState(void* state, char* inputBuffer) {
cbits/lz4.h view
@@ -100,7 +100,7 @@ /*------ Version ------*/ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */-#define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */+#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) @@ -186,7 +186,8 @@ The larger the acceleration value, the faster the algorithm, but also the lesser the compression. It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. An acceleration value of "1" is the same as regular LZ4_compress_default()- Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).+ Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).+ Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c). */ LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); @@ -212,7 +213,18 @@ * New value is necessarily <= input value. * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize) * or 0 if compression fails.-*/+ *+ * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):+ * the produced compressed content could, in specific circumstances,+ * require to be decompressed into a destination buffer larger+ * by at least 1 byte than the content to decompress.+ * If an application uses `LZ4_compress_destSize()`,+ * it's highly recommended to update liblz4 to v1.9.2 or better.+ * If this can't be done or ensured,+ * the receiving decompression function should provide+ * a dstCapacity which is > decompressedSize, by at least 1 byte.+ * See https://github.com/lz4/lz4/issues/859 for details+ */ LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize); @@ -220,25 +232,35 @@ * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src', * into destination buffer 'dst' of size 'dstCapacity'. * Up to 'targetOutputSize' bytes will be decoded.- * The function stops decoding on reaching this objective,- * which can boost performance when only the beginning of a block is required.+ * The function stops decoding on reaching this objective.+ * This can be useful to boost performance+ * whenever only the beginning of a block is required. *- * @return : the number of bytes decoded in `dst` (necessarily <= dstCapacity)+ * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize) * If source stream is detected malformed, function returns a negative result. *- * Note : @return can be < targetOutputSize, if compressed block contains less data.+ * Note 1 : @return can be < targetOutputSize, if compressed block contains less data. *- * Note 2 : this function features 2 parameters, targetOutputSize and dstCapacity,- * and expects targetOutputSize <= dstCapacity.- * It effectively stops decoding on reaching targetOutputSize,+ * Note 2 : targetOutputSize must be <= dstCapacity+ *+ * Note 3 : this function effectively stops decoding on reaching targetOutputSize, * so dstCapacity is kind of redundant.- * This is because in a previous version of this function,- * decoding operation would not "break" a sequence in the middle.- * As a consequence, there was no guarantee that decoding would stop at exactly targetOutputSize,+ * This is because in older versions of this function,+ * decoding operation would still write complete sequences.+ * Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize, * it could write more bytes, though only up to dstCapacity. * Some "margin" used to be required for this operation to work properly.- * This is no longer necessary.- * The function nonetheless keeps its signature, in an effort to not break API.+ * Thankfully, this is no longer necessary.+ * The function nonetheless keeps the same signature, in an effort to preserve API compatibility.+ *+ * Note 4 : If srcSize is the exact size of the block,+ * then targetOutputSize can be any value,+ * including larger than the block's decompressed size.+ * The function will, at most, generate block's decompressed size.+ *+ * Note 5 : If srcSize is _larger_ than block's compressed size,+ * then targetOutputSize **MUST** be <= block's decompressed size.+ * Otherwise, *silent corruption will occur*. */ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity); @@ -547,75 +569,65 @@ #define LZ4_H_98237428734687 /*-************************************************************- * PRIVATE DEFINITIONS+ * Private Definitions ************************************************************** * Do not use these definitions directly. * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.- * Accessing members will expose code to API and/or ABI break in future versions of the library.+ * Accessing members will expose user code to API and/or ABI break in future versions of the library. **************************************************************/ #define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) #define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) #define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)-#include <stdint.h>--typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;-struct LZ4_stream_t_internal {- uint32_t hashTable[LZ4_HASH_SIZE_U32];- uint32_t currentOffset;- uint16_t dirty;- uint16_t tableType;- const uint8_t* dictionary;- const LZ4_stream_t_internal* dictCtx;- uint32_t dictSize;-};--typedef struct {- const uint8_t* externalDict;- size_t extDictSize;- const uint8_t* prefixEnd;- size_t prefixSize;-} LZ4_streamDecode_t_internal;-+# include <stdint.h>+ typedef int8_t LZ4_i8;+ typedef uint8_t LZ4_byte;+ typedef uint16_t LZ4_u16;+ typedef uint32_t LZ4_u32; #else+ typedef signed char LZ4_i8;+ typedef unsigned char LZ4_byte;+ typedef unsigned short LZ4_u16;+ typedef unsigned int LZ4_u32;+#endif typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; struct LZ4_stream_t_internal {- unsigned int hashTable[LZ4_HASH_SIZE_U32];- unsigned int currentOffset;- unsigned short dirty;- unsigned short tableType;- const unsigned char* dictionary;+ LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];+ LZ4_u32 currentOffset;+ LZ4_u32 tableType;+ const LZ4_byte* dictionary; const LZ4_stream_t_internal* dictCtx;- unsigned int dictSize;+ LZ4_u32 dictSize; }; typedef struct {- const unsigned char* externalDict;- const unsigned char* prefixEnd;+ const LZ4_byte* externalDict; size_t extDictSize;+ const LZ4_byte* prefixEnd; size_t prefixSize; } LZ4_streamDecode_t_internal; -#endif /*! LZ4_stream_t :- * information structure to track an LZ4 stream.+ * Do not use below internal definitions directly !+ * Declare or allocate an LZ4_stream_t instead. * LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. * The structure definition can be convenient for static allocation * (on stack, or as part of larger structure). * Init this structure with LZ4_initStream() before first use. * note : only use this definition in association with static linking !- * this definition is not API/ABI safe, and may change in a future version.+ * this definition is not API/ABI safe, and may change in future versions. */-#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4 + ((sizeof(void*)==16) ? 4 : 0) /*AS-400*/ )-#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))+#define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */+#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*)) union LZ4_stream_u {- unsigned long long table[LZ4_STREAMSIZE_U64];+ void* table[LZ4_STREAMSIZE_VOIDP]; LZ4_stream_t_internal internal_donotuse;-} ; /* previously typedef'd to LZ4_stream_t */+}; /* previously typedef'd to LZ4_stream_t */ + /*! LZ4_initStream() : v1.9.0+ * An LZ4_stream_t structure must be initialized at least once. * This is automatically done when invoking LZ4_createStream(),@@ -667,22 +679,21 @@ #ifdef LZ4_DISABLE_DEPRECATE_WARNINGS # define LZ4_DEPRECATED(message) /* disable deprecation warnings */ #else-# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ # define LZ4_DEPRECATED(message) [[deprecated(message)]]-# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)-# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))-# elif (LZ4_GCC_VERSION >= 301)-# define LZ4_DEPRECATED(message) __attribute__((deprecated)) # elif defined(_MSC_VER) # define LZ4_DEPRECATED(message) __declspec(deprecated(message))+# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))+# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))+# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)+# define LZ4_DEPRECATED(message) __attribute__((deprecated)) # else-# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")-# define LZ4_DEPRECATED(message)+# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")+# define LZ4_DEPRECATED(message) /* disabled */ # endif #endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ -/* Obsolete compression functions */+/*! Obsolete compression functions (since v1.7.3) */ LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize); LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize); LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);@@ -690,11 +701,12 @@ LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); -/* Obsolete decompression functions */+/*! Obsolete decompression functions (since v1.8.0) */ LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize); LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); -/* Obsolete streaming functions; degraded functionality; do not use!+/* Obsolete streaming functions (since v1.7.0)+ * degraded functionality; do not use! * * In order to perform streaming compression, these functions depended on data * that is no longer tracked in the state. They have been preserved as well as@@ -708,23 +720,22 @@ LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer); LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state); -/* Obsolete streaming decoding functions */+/*! Obsolete streaming decoding functions (since v1.7.0) */ LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); -/*! LZ4_decompress_fast() : **unsafe!**+/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) : * These functions used to be faster than LZ4_decompress_safe(),- * but it has changed, and they are now slower than LZ4_decompress_safe().+ * but this is no longer the case. They are now slower. * This is because LZ4_decompress_fast() doesn't know the input size,- * and therefore must progress more cautiously in the input buffer to not read beyond the end of block.+ * and therefore must progress more cautiously into the input buffer to not read beyond the end of block. * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability. * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated. * * The last remaining LZ4_decompress_fast() specificity is that * it can decompress a block without knowing its compressed size.- * Such functionality could be achieved in a more secure manner,- * by also providing the maximum size of input buffer,- * but it would require new prototypes, and adaptation of the implementation to this new use case.+ * Such functionality can be achieved in a more secure manner+ * by employing LZ4_decompress_safe_partial(). * * Parameters: * originalSize : is the uncompressed size to regenerate.@@ -739,7 +750,6 @@ * But they may happen if input data is invalid (error or intentional tampering). * As a consequence, use these functions in trusted environments with trusted data **only**. */- LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
cbits/lz4frame.c view
@@ -71,8 +71,8 @@ * towards another library or solution of their choice * by modifying below section. */-#include <stdlib.h> /* malloc, calloc, free */ #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */+# include <stdlib.h> /* malloc, calloc, free */ # define ALLOC(s) malloc(s) # define ALLOC_AND_ZERO(s) calloc(1,(s)) # define FREEMEM(p) free(p)@@ -533,7 +533,7 @@ * 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_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version) { LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t)); if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);@@ -541,20 +541,18 @@ cctxPtr->version = version; cctxPtr->cStage = 0; /* Next stage : init stream */ - *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;+ *LZ4F_compressionContextPtr = cctxPtr; return LZ4F_OK_NoError; } -LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)+LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr) {- LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;- if (cctxPtr != NULL) { /* support free on NULL */- FREEMEM(cctxPtr->lz4CtxPtr); /* works because LZ4_streamHC_t and LZ4_stream_t are simple POD types */+ FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */ FREEMEM(cctxPtr->tmpBuff);- FREEMEM(LZ4F_compressionContext);+ FREEMEM(cctxPtr); } return LZ4F_OK_NoError;@@ -725,6 +723,9 @@ */ size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr) {+ if (preferencesPtr && preferencesPtr->autoFlush) {+ return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0);+ } return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1); } @@ -747,6 +748,7 @@ (int)(srcSize), (int)(srcSize-1), level, cdict); if (cSize == 0) { /* compression failed */+ DEBUGLOG(5, "LZ4F_makeBlock: compression failed, creating a raw block (size %u)", (U32)srcSize); cSize = (U32)srcSize; LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG); memcpy(cSizePtr+BHSize, src, srcSize);@@ -989,6 +991,7 @@ BYTE* dstPtr = dstStart; size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);+ DEBUGLOG(5,"LZ4F_compressEnd: dstCapacity=%u", (unsigned)dstCapacity); if (LZ4F_isError(flushSize)) return flushSize; dstPtr += flushSize; @@ -1002,6 +1005,7 @@ if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) { U32 const xxh = XXH32_digest(&(cctxPtr->xxh)); if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);+ DEBUGLOG(5,"Writing 32-bit content checksum"); LZ4F_writeLE32(dstPtr, xxh); dstPtr+=4; /* content Checksum */ }@@ -1112,6 +1116,7 @@ size_t frameHeaderSize; const BYTE* srcPtr = (const BYTE*)src; + DEBUGLOG(5, "LZ4F_decodeHeader"); /* need to decode header to get frameInfo */ if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */ MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));@@ -1132,8 +1137,10 @@ /* control magic number */ #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION- if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER)+ if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) {+ DEBUGLOG(4, "frame header error : unknown magic number"); return err0r(LZ4F_ERROR_frameType_unknown);+ } #endif dctx->frameInfo.frameType = LZ4F_frame; @@ -1282,15 +1289,20 @@ /* LZ4F_updateDict() :- * only used for LZ4F_blockLinked mode */+ * only used for LZ4F_blockLinked mode+ * Condition : dstPtr != NULL+ */ static void LZ4F_updateDict(LZ4F_dctx* dctx, const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart, unsigned withinTmp) {- if (dctx->dictSize==0)- dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */+ assert(dstPtr != NULL);+ if (dctx->dictSize==0) {+ dctx->dict = (const BYTE*)dstPtr; /* priority to prefix mode */+ }+ assert(dctx->dict != NULL); - if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity, directly within dstBuffer */+ if (dctx->dict + dctx->dictSize == dstPtr) { /* prefix mode, everything within dstBuffer */ dctx->dictSize += dstSize; return; }@@ -1304,9 +1316,10 @@ assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */ - /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOut */+ /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */+ assert(dctx->tmpOutBuffer != NULL); - if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */+ if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */ /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */ assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart); dctx->dictSize += dstSize;@@ -1378,17 +1391,21 @@ const BYTE* const srcEnd = srcStart + *srcSizePtr; const BYTE* srcPtr = srcStart; BYTE* const dstStart = (BYTE*)dstBuffer;- BYTE* const dstEnd = dstStart + *dstSizePtr;+ BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL; BYTE* dstPtr = dstStart; const BYTE* selectedIn = NULL; unsigned doAnotherStage = 1; size_t nextSrcSizeHint = 1; + DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u",+ srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr);+ if (dstBuffer == NULL) assert(*dstSizePtr == 0); MEM_INIT(&optionsNull, 0, sizeof(optionsNull)); if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull; *srcSizePtr = 0; *dstSizePtr = 0;+ assert(dctx != NULL); /* behaves as a state machine */ @@ -1398,6 +1415,7 @@ { case dstage_getFrameHeader:+ DEBUGLOG(6, "dstage_getFrameHeader"); if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */ size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */ if (LZ4F_isError(hSize)) return hSize;@@ -1411,6 +1429,7 @@ /* fall-through */ case dstage_storeFrameHeader:+ DEBUGLOG(6, "dstage_storeFrameHeader"); { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr)); memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy); dctx->tmpInSize += sizeToCopy;@@ -1427,6 +1446,7 @@ break; case dstage_init:+ DEBUGLOG(6, "dstage_init"); if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0); /* internal buffers allocation */ { size_t const bufferNeeded = dctx->maxBlockSize@@ -1480,17 +1500,21 @@ } /* if (dctx->dStage == dstage_storeBlockHeader) */ /* decode block header */- { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;+ { U32 const blockHeader = LZ4F_readLE32(selectedIn);+ size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU; size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;- if (nextCBlockSize==0) { /* frameEnd signal, no more block */+ if (blockHeader==0) { /* frameEnd signal, no more block */+ DEBUGLOG(5, "end of frame"); dctx->dStage = dstage_getSuffix; break; }- if (nextCBlockSize > dctx->maxBlockSize)+ if (nextCBlockSize > dctx->maxBlockSize) { return err0r(LZ4F_ERROR_maxBlockSize_invalid);- if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) {+ }+ if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) { /* next block is uncompressed */ dctx->tmpInTarget = nextCBlockSize;+ DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize); if (dctx->frameInfo.blockChecksumFlag) { (void)XXH32_reset(&dctx->blockChecksum, 0); }@@ -1508,20 +1532,26 @@ } case dstage_copyDirect: /* uncompressed block */- { size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));- size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);- memcpy(dstPtr, srcPtr, sizeToCopy);- if (dctx->frameInfo.blockChecksumFlag) {- (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);- }- if (dctx->frameInfo.contentChecksumFlag)- (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);- if (dctx->frameInfo.contentSize)- dctx->frameRemainingSize -= sizeToCopy;+ DEBUGLOG(6, "dstage_copyDirect");+ { size_t sizeToCopy;+ if (dstPtr == NULL) {+ sizeToCopy = 0;+ } else {+ size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));+ sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);+ memcpy(dstPtr, srcPtr, sizeToCopy);+ if (dctx->frameInfo.blockChecksumFlag) {+ (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);+ }+ if (dctx->frameInfo.contentChecksumFlag)+ (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);+ if (dctx->frameInfo.contentSize)+ dctx->frameRemainingSize -= sizeToCopy; - /* history management (linked blocks only)*/- if (dctx->frameInfo.blockMode == LZ4F_blockLinked)- LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);+ /* history management (linked blocks only)*/+ if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {+ LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);+ } } srcPtr += sizeToCopy; dstPtr += sizeToCopy;@@ -1534,15 +1564,16 @@ break; } dctx->tmpInTarget -= sizeToCopy; /* need to copy more */- nextSrcSizeHint = dctx->tmpInTarget +- +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)- + BHSize /* next header size */;- doAnotherStage = 0;- break; }+ nextSrcSizeHint = dctx->tmpInTarget ++ +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)+ + BHSize /* next header size */;+ doAnotherStage = 0;+ break; /* check block checksum for recently transferred uncompressed block */ case dstage_getBlockChecksum:+ DEBUGLOG(6, "dstage_getBlockChecksum"); { const void* crcSrc; if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) { crcSrc = srcPtr;@@ -1562,8 +1593,12 @@ { U32 const readCRC = LZ4F_readLE32(crcSrc); U32 const calcCRC = XXH32_digest(&dctx->blockChecksum); #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION- if (readCRC != calcCRC)+ DEBUGLOG(6, "compare block checksum");+ if (readCRC != calcCRC) {+ DEBUGLOG(4, "incorrect block checksum: %08X != %08X",+ readCRC, calcCRC); return err0r(LZ4F_ERROR_blockChecksum_invalid);+ } #else (void)readCRC; (void)calcCRC;@@ -1573,6 +1608,7 @@ break; case dstage_getCBlock:+ DEBUGLOG(6, "dstage_getCBlock"); if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) { dctx->tmpInSize = 0; dctx->dStage = dstage_storeCBlock;@@ -1582,7 +1618,7 @@ selectedIn = srcPtr; srcPtr += dctx->tmpInTarget; - if (0) /* jump over next block */+ if (0) /* always jump over next block */ case dstage_storeCBlock: { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize; size_t const inputLeft = (size_t)(srcEnd-srcPtr);@@ -1619,6 +1655,7 @@ const char* dict = (const char*)dctx->dict; size_t dictSize = dctx->dictSize; int decodedSize;+ assert(dstPtr != NULL); if (dict && dictSize > 1 GB) { /* the dictSize param is an int, avoid truncation / sign issues */ dict += dictSize - 64 KB;@@ -1636,8 +1673,9 @@ dctx->frameRemainingSize -= (size_t)decodedSize; /* dictionary management */- if (dctx->frameInfo.blockMode==LZ4F_blockLinked)+ if (dctx->frameInfo.blockMode==LZ4F_blockLinked) { LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);+ } dstPtr += decodedSize; dctx->dStage = dstage_getBlockHeader;@@ -1684,7 +1722,9 @@ /* fall-through */ case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */- { size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));+ DEBUGLOG(6, "dstage_flushOut");+ if (dstPtr != NULL) {+ size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr)); memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy); /* dictionary management */@@ -1693,16 +1733,15 @@ dctx->tmpOutStart += sizeToCopy; dstPtr += sizeToCopy;-- if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */- dctx->dStage = dstage_getBlockHeader; /* get next block */- break;- }- /* could not flush everything : stop there, just request a block header */- doAnotherStage = 0;- nextSrcSizeHint = BHSize;+ }+ if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */+ dctx->dStage = dstage_getBlockHeader; /* get next block */ break; }+ /* could not flush everything : stop there, just request a block header */+ doAnotherStage = 0;+ nextSrcSizeHint = BHSize;+ break; case dstage_getSuffix: if (dctx->frameRemainingSize)@@ -1806,6 +1845,7 @@ LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2); if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */ && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */+ && (dctx->dict != NULL) /* dictionary exists */ && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */ && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */ {@@ -1815,9 +1855,9 @@ const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; if (dctx->tmpOutSize > 64 KB) copySize = 0; if (copySize > preserveSize) copySize = preserveSize;+ assert(dctx->tmpOutBuffer != NULL); - if (copySize > 0)- memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);+ memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize); dctx->dict = dctx->tmpOutBuffer; dctx->dictSize = preserveSize + dctx->tmpOutStart;@@ -1825,8 +1865,7 @@ const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize; size_t const newDictSize = MIN(dctx->dictSize, 64 KB); - if (newDictSize > 0)- memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);+ memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize); dctx->dict = dctx->tmpOutBuffer; dctx->dictSize = newDictSize;
cbits/lz4frame.h view
@@ -66,17 +66,22 @@ *****************************************************************/ /* LZ4_DLL_EXPORT : * Enable exporting of functions when building a Windows DLL- * LZ4FLIB_API :+ * LZ4FLIB_VISIBILITY : * Control library symbols visibility. */+#ifndef LZ4FLIB_VISIBILITY+# if defined(__GNUC__) && (__GNUC__ >= 4)+# define LZ4FLIB_VISIBILITY __attribute__ ((visibility ("default")))+# else+# define LZ4FLIB_VISIBILITY+# endif+#endif #if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)-# define LZ4FLIB_API __declspec(dllexport)+# define LZ4FLIB_API __declspec(dllexport) LZ4FLIB_VISIBILITY #elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)-# define LZ4FLIB_API __declspec(dllimport)-#elif defined(__GNUC__) && (__GNUC__ >= 4)-# define LZ4FLIB_API __attribute__ ((__visibility__ ("default")))+# define LZ4FLIB_API __declspec(dllimport) LZ4FLIB_VISIBILITY #else-# define LZ4FLIB_API+# define LZ4FLIB_API LZ4FLIB_VISIBILITY #endif #ifdef LZ4F_DISABLE_DEPRECATE_WARNINGS@@ -103,7 +108,7 @@ /*-************************************ * Frame compression types- **************************************/+ ************************************* */ /* #define LZ4F_ENABLE_OBSOLETE_ENUMS // uncomment to enable obsolete enums */ #ifdef LZ4F_ENABLE_OBSOLETE_ENUMS # define LZ4F_OBSOLETE_ENUM(x) , LZ4F_DEPRECATE(x) = LZ4F_##x@@ -113,7 +118,8 @@ /* The larger the block size, the (slightly) better the compression ratio, * though there are diminishing returns.- * Larger blocks also increase memory usage on both compression and decompression sides. */+ * Larger blocks also increase memory usage on both compression and decompression sides.+ */ typedef enum { LZ4F_default=0, LZ4F_max64KB=4,@@ -284,7 +290,7 @@ * @return is always the same for a srcSize and prefsPtr. * prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario. * tech details :- * @return includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes.+ * @return if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes. * It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd(). * @return doesn't include frame header, as it was already generated by LZ4F_compressBegin(). */@@ -376,7 +382,7 @@ * note : Frame header size is variable, but is guaranteed to be * >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes. */-size_t LZ4F_headerSize(const void* src, size_t srcSize);+LZ4FLIB_API size_t LZ4F_headerSize(const void* src, size_t srcSize); /*! LZ4F_getFrameInfo() : * This function extracts frame parameters (max blockSize, dictID, etc.).@@ -426,8 +432,10 @@ const void* srcBuffer, size_t* srcSizePtr); /*! LZ4F_decompress() :- * Call this function repetitively to regenerate compressed data from `srcBuffer`.- * The function will read up to *srcSizePtr bytes from srcBuffer,+ * Call this function repetitively to regenerate data compressed in `srcBuffer`.+ *+ * The function requires a valid dctx state.+ * It will read up to *srcSizePtr bytes from srcBuffer, * and decompress data into dstBuffer, of capacity *dstSizePtr. * * The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value).@@ -493,9 +501,9 @@ * Use at your own risk. */ #ifdef LZ4F_PUBLISH_STATIC_FUNCTIONS-#define LZ4FLIB_STATIC_API LZ4FLIB_API+# define LZ4FLIB_STATIC_API LZ4FLIB_API #else-#define LZ4FLIB_STATIC_API+# define LZ4FLIB_STATIC_API #endif
cbits/lz4hc.c view
@@ -53,7 +53,7 @@ #include "lz4hc.h" -/*=== Common LZ4 definitions ===*/+/*=== Common definitions ===*/ #if defined(__GNUC__) # pragma GCC diagnostic ignored "-Wunused-function" #endif@@ -61,15 +61,16 @@ # pragma clang diagnostic ignored "-Wunused-function" #endif -/*=== Enums ===*/-typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;-- #define LZ4_COMMONDEFS_ONLY #ifndef LZ4_SRC_INCLUDED #include "lz4.c" /* LZ4_count, constants, mem */ #endif ++/*=== Enums ===*/+typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;++ /*=== Constants ===*/ #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH) #define LZ4_OPT_NUM (1<<12)@@ -92,7 +93,7 @@ **************************************/ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) {- MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));+ MEM_INIT(hc4->hashTable, 0, sizeof(hc4->hashTable)); MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); } @@ -161,8 +162,7 @@ static U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern) { size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3;- if (bitsToRotate == 0)- return pattern;+ if (bitsToRotate == 0) return pattern; return LZ4HC_rotl32(pattern, (int)bitsToRotate); } @@ -172,7 +172,8 @@ LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32) { const BYTE* const iStart = ip;- reg_t const pattern = (sizeof(pattern)==8) ? (reg_t)pattern32 + (((reg_t)pattern32) << 32) : pattern32;+ reg_t const pattern = (sizeof(pattern)==8) ?+ (reg_t)pattern32 + (((reg_t)pattern32) << (sizeof(pattern)*4)) : pattern32; while (likely(ip < iEnd-(sizeof(pattern)-1))) { reg_t const diff = LZ4_read_ARCH(ip) ^ pattern;@@ -270,7 +271,7 @@ DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)", matchIndex, lowestMatchIndex); - while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) {+ while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) { int matchLength=0; nbAttempts--; assert(matchIndex < ipIndex);@@ -389,8 +390,8 @@ if (lookBackLength==0) { /* no back possible */ size_t const maxML = MIN(currentSegmentLength, srcPatternLength); if ((size_t)longest < maxML) {- assert(base + matchIndex < ip);- if (ip - (base+matchIndex) > LZ4_DISTANCE_MAX) break;+ assert(base + matchIndex != ip);+ if ((size_t)(ip - base) - matchIndex > LZ4_DISTANCE_MAX) break; assert(maxML < 2 GB); longest = (int)maxML; *matchpos = base + matchIndex; /* virtual pos, relative to ip, to retrieve offset */@@ -410,7 +411,7 @@ } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */ if ( dict == usingDictCtxHc- && nbAttempts+ && nbAttempts > 0 && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) { size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base); U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];@@ -460,74 +461,90 @@ * @return : 0 if ok, * 1 if buffer issue detected */ LZ4_FORCE_INLINE int LZ4HC_encodeSequence (- const BYTE** ip,- BYTE** op,- const BYTE** anchor,+ const BYTE** _ip,+ BYTE** _op,+ const BYTE** _anchor, int matchLength, const BYTE* const match, limitedOutput_directive limit, BYTE* oend) {+#define ip (*_ip)+#define op (*_op)+#define anchor (*_anchor)+ size_t length;- BYTE* const token = (*op)++;+ BYTE* const token = op++; #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6) static const BYTE* start = NULL; static U32 totalCost = 0;- U32 const pos = (start==NULL) ? 0 : (U32)(*anchor - start);- U32 const ll = (U32)(*ip - *anchor);+ U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);+ U32 const ll = (U32)(ip - anchor); U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0; U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0; U32 const cost = 1 + llAdd + ll + 2 + mlAdd;- if (start==NULL) start = *anchor; /* only works for single segment */+ if (start==NULL) start = anchor; /* only works for single segment */ /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */- DEBUGLOG(6, "pos:%7u -- literals:%3u, match:%4i, offset:%5u, cost:%3u + %u",+ DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u", pos,- (U32)(*ip - *anchor), matchLength, (U32)(*ip-match),+ (U32)(ip - anchor), matchLength, (U32)(ip-match), cost, totalCost); totalCost += cost; #endif /* Encode Literal length */- length = (size_t)(*ip - *anchor);- if ((limit) && ((*op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */+ length = (size_t)(ip - anchor);+ LZ4_STATIC_ASSERT(notLimited == 0);+ /* Check output limit */+ if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {+ DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",+ (int)length, (int)(oend - op));+ return 1;+ } if (length >= RUN_MASK) { size_t len = length - RUN_MASK; *token = (RUN_MASK << ML_BITS);- for(; len >= 255 ; len -= 255) *(*op)++ = 255;- *(*op)++ = (BYTE)len;+ for(; len >= 255 ; len -= 255) *op++ = 255;+ *op++ = (BYTE)len; } else { *token = (BYTE)(length << ML_BITS); } /* Copy Literals */- LZ4_wildCopy8(*op, *anchor, (*op) + length);- *op += length;+ LZ4_wildCopy8(op, anchor, op + length);+ op += length; /* Encode Offset */- assert( (*ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */- LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;+ assert( (ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */+ LZ4_writeLE16(op, (U16)(ip - match)); op += 2; /* Encode MatchLength */ assert(matchLength >= MINMATCH); length = (size_t)matchLength - MINMATCH;- if ((limit) && (*op + (length / 255) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */+ if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {+ DEBUGLOG(6, "Not enough room to write match length");+ return 1; /* Check output limit */+ } if (length >= ML_MASK) { *token += ML_MASK; length -= ML_MASK;- for(; length >= 510 ; length -= 510) { *(*op)++ = 255; *(*op)++ = 255; }- if (length >= 255) { length -= 255; *(*op)++ = 255; }- *(*op)++ = (BYTE)length;+ for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }+ if (length >= 255) { length -= 255; *op++ = 255; }+ *op++ = (BYTE)length; } else { *token += (BYTE)(length); } /* Prepare next loop */- *ip += matchLength;- *anchor = *ip;+ ip += matchLength;+ anchor = ip; return 0; }+#undef ip+#undef op+#undef anchor LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( LZ4HC_CCtx_internal* const ctx,@@ -535,7 +552,7 @@ char* const dest, int* srcSizePtr, int const maxOutputSize,- unsigned maxNbAttempts,+ int maxNbAttempts, const limitedOutput_directive limit, const dictCtx_directive dict )@@ -565,7 +582,7 @@ /* init */ *srcSizePtr = 0; if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */- if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */+ if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ /* Main Loop */ while (ip <= mflimit) {@@ -637,7 +654,11 @@ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; ip = start2; optr = op;- if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) goto _dest_overflow;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) {+ ml = ml2;+ ref = ref2;+ goto _dest_overflow;+ } continue; } @@ -709,17 +730,18 @@ _last_literals: /* Encode Last Literals */ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */- size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255;- size_t const totalSize = 1 + litLength + lastRunSize;+ size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;+ size_t const totalSize = 1 + llAdd + lastRunSize; if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ if (limit && (op + totalSize > oend)) {- if (limit == limitedOutput) return 0; /* Check output limit */+ if (limit == limitedOutput) return 0; /* adapt lastRunSize to fill 'dest' */- lastRunSize = (size_t)(oend - op) - 1;- litLength = (lastRunSize + 255 - RUN_MASK) / 255;- lastRunSize -= litLength;+ lastRunSize = (size_t)(oend - op) - 1 /*token*/;+ llAdd = (lastRunSize + 256 - RUN_MASK) / 256;+ lastRunSize -= llAdd; }- ip = anchor + lastRunSize;+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);+ ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */ if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK;@@ -739,9 +761,25 @@ _dest_overflow: if (limit == fillOutput) {+ /* Assumption : ip, anchor, ml and ref must be set correctly */+ size_t const ll = (size_t)(ip - anchor);+ size_t const ll_addbytes = (ll + 240) / 255;+ size_t const ll_totalCost = 1 + ll_addbytes + ll;+ BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */+ DEBUGLOG(6, "Last sequence overflowing"); op = optr; /* restore correct out pointer */+ if (op + ll_totalCost <= maxLitPos) {+ /* ll validated; now adjust match length */+ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));+ size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);+ assert(maxMlSize < INT_MAX); assert(ml >= 0);+ if ((size_t)ml > maxMlSize) ml = (int)maxMlSize;+ if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ml >= MFLIMIT) {+ LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, notLimited, oend);+ } } goto _last_literals; }+ /* compression failed */ return 0; } @@ -752,7 +790,7 @@ int const nbSearches, size_t sufficient_len, const limitedOutput_directive limit, int const fullUpdate, const dictCtx_directive dict,- HCfavor_e favorDecSpeed);+ const HCfavor_e favorDecSpeed); LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal (@@ -769,7 +807,7 @@ typedef enum { lz4hc, lz4opt } lz4hc_strat_e; typedef struct { lz4hc_strat_e strat;- U32 nbSearches;+ int nbSearches; U32 targetLength; } cParams_t; static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = {@@ -788,7 +826,8 @@ { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ }; - DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d)", ctx, src, *srcSizePtr);+ DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",+ ctx, src, *srcSizePtr, limit); if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */@@ -808,7 +847,7 @@ assert(cParam.strat == lz4opt); result = LZ4HC_compress_optimal(ctx, src, dst, srcSizePtr, dstCapacity,- (int)cParam.nbSearches, cParam.targetLength, limit,+ cParam.nbSearches, cParam.targetLength, limit, cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */ dict, favor); }@@ -881,27 +920,22 @@ int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); } -#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :- * it reports an aligment of 8-bytes,- * while actually aligning LZ4_streamHC_t on 4 bytes. */ static size_t LZ4_streamHC_t_alignment(void) {- struct { char c; LZ4_streamHC_t t; } t_a;- return sizeof(t_a) - sizeof(t_a.t);-}+#if LZ4_ALIGN_TEST+ typedef struct { char c; LZ4_streamHC_t t; } t_a;+ return sizeof(t_a) - sizeof(LZ4_streamHC_t);+#else+ return 1; /* effectively disabled */ #endif+} /* state is presumed correctly initialized, * in which case its size and alignment have already been validate */ int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;-#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :- * it reports an aligment of 8-bytes,- * while actually aligning LZ4_streamHC_t on 4 bytes. */- assert(((size_t)state & (LZ4_streamHC_t_alignment() - 1)) == 0); /* check alignment */-#endif- if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */+ if (!LZ4_isAligned(state, LZ4_streamHC_t_alignment())) return 0; LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel); LZ4HC_init_internal (ctx, (const BYTE*)src); if (dstCapacity < LZ4_compressBound(srcSize))@@ -950,10 +984,11 @@ /* allocation */ LZ4_streamHC_t* LZ4_createStreamHC(void) {- LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t));- if (LZ4_streamHCPtr==NULL) return NULL;- LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); /* full initialization, malloc'ed buffer can be full of garbage */- return LZ4_streamHCPtr;+ LZ4_streamHC_t* const state =+ (LZ4_streamHC_t*)ALLOC_AND_ZERO(sizeof(LZ4_streamHC_t));+ if (state == NULL) return NULL;+ LZ4_setCompressionLevel(state, LZ4HC_CLEVEL_DEFAULT);+ return state; } int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr)@@ -968,22 +1003,16 @@ LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) { LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer;- if (buffer == NULL) return NULL;- if (size < sizeof(LZ4_streamHC_t)) return NULL;-#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :- * it reports an aligment of 8-bytes,- * while actually aligning LZ4_streamHC_t on 4 bytes. */- if (((size_t)buffer) & (LZ4_streamHC_t_alignment() - 1)) return NULL; /* alignment check */-#endif /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE);- DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", LZ4_streamHCPtr, (unsigned)size);- /* end-base will trigger a clearTable on starting compression */- LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1;- LZ4_streamHCPtr->internal_donotuse.base = NULL;- LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL;- LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0;- LZ4_streamHCPtr->internal_donotuse.dirty = 0;+ DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size);+ /* check conditions */+ if (buffer == NULL) return NULL;+ if (size < sizeof(LZ4_streamHC_t)) return NULL;+ if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL;+ /* init */+ { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse);+ MEM_INIT(hcstate, 0, sizeof(*hcstate)); } LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); return LZ4_streamHCPtr; }@@ -1028,7 +1057,7 @@ const char* dictionary, int dictSize) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;- DEBUGLOG(4, "LZ4_loadDictHC(%p, %p, %d)", LZ4_streamHCPtr, dictionary, dictSize);+ DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d)", LZ4_streamHCPtr, dictionary, dictSize); assert(LZ4_streamHCPtr != NULL); if (dictSize > 64 KB) { dictionary += (size_t)dictSize - 64 KB;@@ -1069,14 +1098,15 @@ ctxPtr->dictCtx = NULL; } -static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,- const char* src, char* dst,- int* srcSizePtr, int dstCapacity,- limitedOutput_directive limit)+static int+LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,+ const char* src, char* dst,+ int* srcSizePtr, int dstCapacity,+ limitedOutput_directive limit) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;- DEBUGLOG(4, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d)",- LZ4_streamHCPtr, src, *srcSizePtr);+ DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",+ LZ4_streamHCPtr, src, *srcSizePtr, limit); assert(ctxPtr != NULL); /* auto-init if forgotten */ if (ctxPtr->base == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src);@@ -1100,8 +1130,7 @@ if (sourceEnd > dictEnd) sourceEnd = dictEnd; ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;- }- }+ } } return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit); }@@ -1121,23 +1150,30 @@ -/* dictionary saving */-+/* LZ4_saveDictHC :+ * save history content+ * into a user-provided buffer+ * which is then used to continue compression+ */ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize) { LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse; int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));- DEBUGLOG(4, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);+ DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);+ assert(prefixSize >= 0); if (dictSize > 64 KB) dictSize = 64 KB; if (dictSize < 4) dictSize = 0; if (dictSize > prefixSize) dictSize = prefixSize;- memmove(safeBuffer, streamPtr->end - dictSize, dictSize);+ if (safeBuffer == NULL) assert(dictSize == 0);+ if (dictSize > 0)+ memmove(safeBuffer, streamPtr->end - dictSize, dictSize); { U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); streamPtr->end = (const BYTE*)safeBuffer + dictSize; streamPtr->base = streamPtr->end - endIndex; streamPtr->dictLimit = endIndex - (U32)dictSize; streamPtr->lowLimit = endIndex - (U32)dictSize;- if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;+ if (streamPtr->nextToUpdate < streamPtr->dictLimit)+ streamPtr->nextToUpdate = streamPtr->dictLimit; } return dictSize; }@@ -1287,8 +1323,13 @@ const dictCtx_directive dict, const HCfavor_e favorDecSpeed) {+ int retval = 0; #define TRAILING_LITERALS 3+#ifdef LZ4HC_HEAPMODE+ LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS));+#else LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */+#endif const BYTE* ip = (const BYTE*) source; const BYTE* anchor = ip;@@ -1298,15 +1339,19 @@ BYTE* op = (BYTE*) dst; BYTE* opSaved = (BYTE*) dst; BYTE* oend = op + dstCapacity;+ int ovml = MINMATCH; /* overflow - last sequence */+ const BYTE* ovref = NULL; /* init */+#ifdef LZ4HC_HEAPMODE+ if (opt == NULL) goto _return_label;+#endif DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity); *srcSizePtr = 0; if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1; /* Main Loop */- assert(ip - anchor < LZ4_MAX_INPUT_SIZE); while (ip <= mflimit) { int const llen = (int)(ip - anchor); int best_mlen, best_off;@@ -1320,8 +1365,11 @@ int const firstML = firstMatch.len; const BYTE* const matchPos = ip - firstMatch.off; opSaved = op;- if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) /* updates ip, op and anchor */+ if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) { /* updates ip, op and anchor */+ ovml = firstML;+ ovref = matchPos; goto _dest_overflow;+ } continue; } @@ -1463,7 +1511,7 @@ best_off = opt[last_match_pos].off; cur = last_match_pos - best_mlen; - encode: /* cur, last_match_pos, best_mlen, best_off must be set */+encode: /* cur, last_match_pos, best_mlen, best_off must be set */ assert(cur < LZ4_OPT_NUM); assert(last_match_pos >= 1); /* == 1 when only one candidate */ DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos);@@ -1493,25 +1541,31 @@ assert(ml >= MINMATCH); assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX)); opSaved = op;- if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) /* updates ip, op and anchor */+ if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) { /* updates ip, op and anchor */+ ovml = ml;+ ovref = ip - offset; goto _dest_overflow;- } }+ } } } } /* while (ip <= mflimit) */ - _last_literals:+_last_literals: /* Encode Last Literals */ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */- size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255;- size_t const totalSize = 1 + litLength + lastRunSize;+ size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;+ size_t const totalSize = 1 + llAdd + lastRunSize; if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ if (limit && (op + totalSize > oend)) {- if (limit == limitedOutput) return 0; /* Check output limit */+ if (limit == limitedOutput) { /* Check output limit */+ retval = 0;+ goto _return_label;+ } /* adapt lastRunSize to fill 'dst' */- lastRunSize = (size_t)(oend - op) - 1;- litLength = (lastRunSize + 255 - RUN_MASK) / 255;- lastRunSize -= litLength;+ lastRunSize = (size_t)(oend - op) - 1 /*token*/;+ llAdd = (lastRunSize + 256 - RUN_MASK) / 256;+ lastRunSize -= llAdd; }- ip = anchor + lastRunSize;+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);+ ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */ if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK;@@ -1527,12 +1581,35 @@ /* End */ *srcSizePtr = (int) (((const char*)ip) - source);- return (int) ((char*)op-dst);+ retval = (int) ((char*)op-dst);+ goto _return_label; - _dest_overflow:- if (limit == fillOutput) {- op = opSaved; /* restore correct out pointer */- goto _last_literals;- }- return 0;- }+_dest_overflow:+if (limit == fillOutput) {+ /* Assumption : ip, anchor, ovml and ovref must be set correctly */+ size_t const ll = (size_t)(ip - anchor);+ size_t const ll_addbytes = (ll + 240) / 255;+ size_t const ll_totalCost = 1 + ll_addbytes + ll;+ BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */+ DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend-1-opSaved));+ op = opSaved; /* restore correct out pointer */+ if (op + ll_totalCost <= maxLitPos) {+ /* ll validated; now adjust match length */+ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));+ size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);+ assert(maxMlSize < INT_MAX); assert(ovml >= 0);+ if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize;+ if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) {+ DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml);+ DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor);+ LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovref, notLimited, oend);+ DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor);+ } }+ goto _last_literals;+}+_return_label:+#ifdef LZ4HC_HEAPMODE+ FREEMEM(opt);+#endif+ return retval;+}
cbits/lz4hc.h view
@@ -198,57 +198,32 @@ #define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1) -#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)-#include <stdint.h>- typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal; struct LZ4HC_CCtx_internal {- uint32_t hashTable[LZ4HC_HASHTABLESIZE];- uint16_t chainTable[LZ4HC_MAXD];- const uint8_t* end; /* next block here to continue on current prefix */- const uint8_t* base; /* All index relative to this position */- const uint8_t* dictBase; /* alternate base for extDict */- uint32_t dictLimit; /* below that point, need extDict */- uint32_t lowLimit; /* below that point, no more dict */- uint32_t nextToUpdate; /* index from which to continue dictionary update */- short compressionLevel;- int8_t favorDecSpeed; /* favor decompression speed if this flag set,- otherwise, favor compression ratio */- int8_t dirty; /* stream has to be fully reset if this flag is set */+ LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];+ LZ4_u16 chainTable[LZ4HC_MAXD];+ const LZ4_byte* end; /* next block here to continue on current prefix */+ const LZ4_byte* base; /* All index relative to this position */+ const LZ4_byte* dictBase; /* alternate base for extDict */+ LZ4_u32 dictLimit; /* below that point, need extDict */+ LZ4_u32 lowLimit; /* below that point, no more dict */+ LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */+ short compressionLevel;+ LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,+ otherwise, favor compression ratio */+ LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */ const LZ4HC_CCtx_internal* dictCtx; }; -#else -typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;-struct LZ4HC_CCtx_internal-{- unsigned int hashTable[LZ4HC_HASHTABLESIZE];- unsigned short chainTable[LZ4HC_MAXD];- const unsigned char* end; /* next block here to continue on current prefix */- const unsigned char* base; /* All index relative to this position */- const unsigned char* dictBase; /* alternate base for extDict */- unsigned int dictLimit; /* below that point, need extDict */- unsigned int lowLimit; /* below that point, no more dict */- unsigned int nextToUpdate; /* index from which to continue dictionary update */- short compressionLevel;- char favorDecSpeed; /* favor decompression speed if this flag set,- otherwise, favor compression ratio */- char dirty; /* stream has to be fully reset if this flag is set */- const LZ4HC_CCtx_internal* dictCtx;-};--#endif-- /* Do not use these definitions directly ! * Declare or allocate an LZ4_streamHC_t instead. */-#define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56 + ((sizeof(void*)==16) ? 56 : 0) /* AS400*/ ) /* 262200 or 262256*/-#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t))+#define LZ4_STREAMHCSIZE 262200 /* static size, for inter-version compatibility */+#define LZ4_STREAMHCSIZE_VOIDP (LZ4_STREAMHCSIZE / sizeof(void*)) union LZ4_streamHC_u {- size_t table[LZ4_STREAMHCSIZE_SIZET];+ void* table[LZ4_STREAMHCSIZE_VOIDP]; LZ4HC_CCtx_internal internal_donotuse; }; /* previously typedef'd to LZ4_streamHC_t */
lz4-hs.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: lz4-hs-version: 0.1.5.0+version: 0.1.5.1 license: BSD-3-Clause license-file: LICENSE copyright: Copyright: (c) 2020 Vanessa McHale@@ -67,7 +67,7 @@ main-is: Spec.hs hs-source-dirs: test default-language: Haskell2010- ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+ ghc-options: -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall build-depends: base -any, lz4-hs -any,@@ -94,7 +94,7 @@ main-is: Mem.hs hs-source-dirs: mem default-language: Haskell2010- ghc-options: -Wall+ ghc-options: -Wall -rtsopts build-depends: base -any, lz4-hs -any,