Bump LZ4 to 1.9.4.

This commit is contained in:
Bartosz Taudul 2022-08-16 14:43:50 +02:00
parent 3d9d242153
commit 06b986ad90
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
4 changed files with 678 additions and 364 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* /*
* LZ4 - Fast LZ compression algorithm * LZ4 - Fast LZ compression algorithm
* Header File * Header File
* Copyright (C) 2011-present, Yann Collet. * Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@ -95,39 +95,80 @@
# define LZ4LIB_API LZ4LIB_VISIBILITY # define LZ4LIB_API LZ4LIB_VISIBILITY
#endif #endif
/*! LZ4_FREESTANDING :
* When this macro is set to 1, it enables "freestanding mode" that is
* suitable for typical freestanding environment which doesn't support
* standard C library.
*
* - LZ4_FREESTANDING is a compile-time switch.
* - It requires the following macros to be defined:
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
* - It only enables LZ4/HC functions which don't use heap.
* All LZ4F_* functions are not supported.
* - See tests/freestanding.c to check its basic setup.
*/
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
# define LZ4_HEAPMODE 0
# define LZ4HC_HEAPMODE 0
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
# if !defined(LZ4_memcpy)
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
# endif
# if !defined(LZ4_memset)
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
# endif
# if !defined(LZ4_memmove)
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
# endif
#elif ! defined(LZ4_FREESTANDING)
# define LZ4_FREESTANDING 0
#endif
/*------ Version ------*/ /*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */ #define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ #define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE #define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
#define LZ4_QUOTE(str) #str #define LZ4_QUOTE(str) #str
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) #define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) #define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
namespace tracy namespace tracy
{ {
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */ LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
/*-************************************ /*-************************************
* Tuning parameter * Tuning parameter
**************************************/ **************************************/
#define LZ4_MEMORY_USAGE_MIN 10
#define LZ4_MEMORY_USAGE_DEFAULT 14
#define LZ4_MEMORY_USAGE_MAX 20
/*! /*!
* LZ4_MEMORY_USAGE : * LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
* Increasing memory usage improves compression ratio. * Increasing memory usage improves compression ratio, at the cost of speed.
* Reduced memory usage may improve speed, thanks to better cache locality. * Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/ */
#ifndef LZ4_MEMORY_USAGE #ifndef LZ4_MEMORY_USAGE
# define LZ4_MEMORY_USAGE 14 # define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
#endif #endif
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
# error "LZ4_MEMORY_USAGE is too small !"
#endif
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
# error "LZ4_MEMORY_USAGE is too large !"
#endif
/*-************************************ /*-************************************
* Simple Functions * Simple Functions
@ -271,8 +312,25 @@ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcS
***********************************************/ ***********************************************/
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
/**
Note about RC_INVOKED
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
and reports warning "RC4011: identifier truncated".
- To eliminate the warning, we surround long preprocessor symbol with
"#if !defined(RC_INVOKED) ... #endif" block that means
"skip this block when rc.exe is trying to read it".
*/
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_resetStream_fast() : v1.9.0+ /*! LZ4_resetStream_fast() : v1.9.0+
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
@ -356,8 +414,12 @@ typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
* creation / destruction of streaming decompression tracking context. * creation / destruction of streaming decompression tracking context.
* A tracking context can be re-used multiple times. * A tracking context can be re-used multiple times.
*/ */
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_setStreamDecode() : /*! LZ4_setStreamDecode() :
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times. * An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
@ -407,7 +469,10 @@ LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression, * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block. * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
*/ */
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity); LZ4LIB_API int
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
const char* src, char* dst,
int srcSize, int dstCapacity);
/*! LZ4_decompress_*_usingDict() : /*! LZ4_decompress_*_usingDict() :
@ -418,7 +483,16 @@ LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecod
* Performance tip : Decompression speed can be substantially increased * Performance tip : Decompression speed can be substantially increased
* when dst == dictStart + dictSize. * when dst == dictStart + dictSize.
*/ */
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize); LZ4LIB_API int
LZ4_decompress_safe_usingDict(const char* src, char* dst,
int srcSize, int dstCapacity,
const char* dictStart, int dictSize);
LZ4LIB_API int
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
int compressedSize,
int targetOutputSize, int maxOutputSize,
const char* dictStart, int dictSize);
} }
@ -501,13 +575,15 @@ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const c
* stream (and source buffer) must remain in-place / accessible / unchanged * stream (and source buffer) must remain in-place / accessible / unchanged
* through the completion of the first compression call on the stream. * through the completion of the first compression call on the stream.
*/ */
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream); LZ4LIB_STATIC_API void
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
const LZ4_stream_t* dictionaryStream);
/*! In-place compression and decompression /*! In-place compression and decompression
* *
* It's possible to have input and output sharing the same buffer, * It's possible to have input and output sharing the same buffer,
* for highly contrained memory environments. * for highly constrained memory environments.
* In both cases, it requires input to lay at the end of the buffer, * In both cases, it requires input to lay at the end of the buffer,
* and decompression to start at beginning of the buffer. * and decompression to start at beginning of the buffer.
* Buffer size must feature some margin, hence be larger than final size. * Buffer size must feature some margin, hence be larger than final size.
@ -570,6 +646,8 @@ LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const
#endif /* LZ4_STATIC_3504398509 */ #endif /* LZ4_STATIC_3504398509 */
#endif /* LZ4_STATIC_LINKING_ONLY */ #endif /* LZ4_STATIC_LINKING_ONLY */
#ifndef TRACY_LZ4_H_98237428734687 #ifndef TRACY_LZ4_H_98237428734687
#define TRACY_LZ4_H_98237428734687 #define TRACY_LZ4_H_98237428734687
@ -599,38 +677,26 @@ namespace tracy
typedef unsigned int LZ4_u32; typedef unsigned int LZ4_u32;
#endif #endif
/*! LZ4_stream_t :
* Never ever use below internal definitions directly !
* These definitions are not API/ABI safe, and may change in future versions.
* If you need static allocation, declare or allocate an LZ4_stream_t object.
**/
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
struct LZ4_stream_t_internal { struct LZ4_stream_t_internal {
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32]; LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
LZ4_u32 currentOffset;
LZ4_u32 tableType;
const LZ4_byte* dictionary; const LZ4_byte* dictionary;
const LZ4_stream_t_internal* dictCtx; const LZ4_stream_t_internal* dictCtx;
LZ4_u32 currentOffset;
LZ4_u32 tableType;
LZ4_u32 dictSize; LZ4_u32 dictSize;
/* Implicit padding to ensure structure is aligned */
}; };
typedef struct { #define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
const LZ4_byte* externalDict;
size_t extDictSize;
const LZ4_byte* prefixEnd;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
/*! LZ4_stream_t :
* 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 future versions.
*/
#define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */
#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
union LZ4_stream_u { union LZ4_stream_u {
void* table[LZ4_STREAMSIZE_VOIDP]; char minStateSize[LZ4_STREAM_MINSIZE];
LZ4_stream_t_internal internal_donotuse; LZ4_stream_t_internal internal_donotuse;
}; /* previously typedef'd to LZ4_stream_t */ }; /* previously typedef'd to LZ4_stream_t */
@ -648,21 +714,25 @@ union LZ4_stream_u {
* In which case, the function will @return NULL. * In which case, the function will @return NULL.
* Note2: An LZ4_stream_t structure guarantees correct alignment and size. * Note2: An LZ4_stream_t structure guarantees correct alignment and size.
* Note3: Before v1.9.0, use LZ4_resetStream() instead * Note3: Before v1.9.0, use LZ4_resetStream() instead
*/ **/
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
/*! LZ4_streamDecode_t : /*! LZ4_streamDecode_t :
* information structure to track an LZ4 stream during decompression. * Never ever use below internal definitions directly !
* init this structure using LZ4_setStreamDecode() before first use. * These definitions are not API/ABI safe, and may change in future versions.
* note : only use in association with static linking ! * If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
* this definition is not API/ABI safe, **/
* and may change in a future version ! typedef struct {
*/ const LZ4_byte* externalDict;
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ ) const LZ4_byte* prefixEnd;
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) size_t extDictSize;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
#define LZ4_STREAMDECODE_MINSIZE 32
union LZ4_streamDecode_u { union LZ4_streamDecode_u {
unsigned long long table[LZ4_STREAMDECODESIZE_U64]; char minStateSize[LZ4_STREAMDECODE_MINSIZE];
LZ4_streamDecode_t_internal internal_donotuse; LZ4_streamDecode_t_internal internal_donotuse;
} ; /* previously typedef'd to LZ4_streamDecode_t */ } ; /* previously typedef'd to LZ4_streamDecode_t */

View File

@ -1,6 +1,6 @@
/* /*
LZ4 HC - High Compression Mode of LZ4 LZ4 HC - High Compression Mode of LZ4
Copyright (C) 2011-2017, Yann Collet. Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@ -42,7 +42,7 @@
* Select how default compression function will allocate workplace memory, * Select how default compression function will allocate workplace memory,
* in stack (0:fastest), or in heap (1:requires malloc()). * in stack (0:fastest), or in heap (1:requires malloc()).
* Since workplace is rather large, heap mode is recommended. * Since workplace is rather large, heap mode is recommended.
*/ **/
#ifndef LZ4HC_HEAPMODE #ifndef LZ4HC_HEAPMODE
# define LZ4HC_HEAPMODE 1 # define LZ4HC_HEAPMODE 1
#endif #endif
@ -102,18 +102,20 @@ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4)
static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start)
{ {
uptrval startingOffset = (uptrval)(hc4->end - hc4->base); size_t const bufferSize = (size_t)(hc4->end - hc4->prefixStart);
if (startingOffset > 1 GB) { size_t newStartingOffset = bufferSize + hc4->dictLimit;
assert(newStartingOffset >= bufferSize); /* check overflow */
if (newStartingOffset > 1 GB) {
LZ4HC_clearTables(hc4); LZ4HC_clearTables(hc4);
startingOffset = 0; newStartingOffset = 0;
} }
startingOffset += 64 KB; newStartingOffset += 64 KB;
hc4->nextToUpdate = (U32) startingOffset; hc4->nextToUpdate = (U32)newStartingOffset;
hc4->base = start - startingOffset; hc4->prefixStart = start;
hc4->end = start; hc4->end = start;
hc4->dictBase = start - startingOffset; hc4->dictStart = start;
hc4->dictLimit = (U32) startingOffset; hc4->dictLimit = (U32)newStartingOffset;
hc4->lowLimit = (U32) startingOffset; hc4->lowLimit = (U32)newStartingOffset;
} }
@ -122,12 +124,15 @@ LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
{ {
U16* const chainTable = hc4->chainTable; U16* const chainTable = hc4->chainTable;
U32* const hashTable = hc4->hashTable; U32* const hashTable = hc4->hashTable;
const BYTE* const base = hc4->base; const BYTE* const prefixPtr = hc4->prefixStart;
U32 const target = (U32)(ip - base); U32 const prefixIdx = hc4->dictLimit;
U32 const target = (U32)(ip - prefixPtr) + prefixIdx;
U32 idx = hc4->nextToUpdate; U32 idx = hc4->nextToUpdate;
assert(ip >= prefixPtr);
assert(target >= prefixIdx);
while (idx < target) { while (idx < target) {
U32 const h = LZ4HC_hashPtr(base+idx); U32 const h = LZ4HC_hashPtr(prefixPtr+idx-prefixIdx);
size_t delta = idx - hashTable[h]; size_t delta = idx - hashTable[h];
if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX; if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX;
DELTANEXTU16(chainTable, idx) = (U16)delta; DELTANEXTU16(chainTable, idx) = (U16)delta;
@ -196,15 +201,14 @@ LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32)
BYTE const byte = (BYTE)(pattern >> bitOffset); BYTE const byte = (BYTE)(pattern >> bitOffset);
if (*ip != byte) break; if (*ip != byte) break;
ip ++; bitOffset -= 8; ip ++; bitOffset -= 8;
} } }
}
return (unsigned)(ip - iStart); return (unsigned)(ip - iStart);
} }
/* LZ4HC_reverseCountPattern() : /* LZ4HC_reverseCountPattern() :
* pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!)
* read using natural platform endianess */ * read using natural platform endianness */
static unsigned static unsigned
LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern) LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern)
{ {
@ -214,7 +218,7 @@ LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern)
if (LZ4_read32(ip-4) != pattern) break; if (LZ4_read32(ip-4) != pattern) break;
ip -= 4; ip -= 4;
} }
{ const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianess */ { const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianness */
while (likely(ip>iLow)) { while (likely(ip>iLow)) {
if (ip[-1] != *bytePtr) break; if (ip[-1] != *bytePtr) break;
ip--; bytePtr--; ip--; bytePtr--;
@ -237,28 +241,28 @@ typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e;
LZ4_FORCE_INLINE int LZ4_FORCE_INLINE int
LZ4HC_InsertAndGetWiderMatch ( LZ4HC_InsertAndGetWiderMatch (
LZ4HC_CCtx_internal* hc4, LZ4HC_CCtx_internal* const hc4,
const BYTE* const ip, const BYTE* const ip,
const BYTE* const iLowLimit, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const BYTE* const iHighLimit, int longest,
int longest, const BYTE** matchpos,
const BYTE** matchpos, const BYTE** startpos,
const BYTE** startpos, const int maxNbAttempts,
const int maxNbAttempts, const int patternAnalysis, const int chainSwap,
const int patternAnalysis, const dictCtx_directive dict,
const int chainSwap, const HCfavor_e favorDecSpeed)
const dictCtx_directive dict,
const HCfavor_e favorDecSpeed)
{ {
U16* const chainTable = hc4->chainTable; U16* const chainTable = hc4->chainTable;
U32* const HashTable = hc4->hashTable; U32* const HashTable = hc4->hashTable;
const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx; const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx;
const BYTE* const base = hc4->base; const BYTE* const prefixPtr = hc4->prefixStart;
const U32 dictLimit = hc4->dictLimit; const U32 prefixIdx = hc4->dictLimit;
const BYTE* const lowPrefixPtr = base + dictLimit; const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;
const U32 ipIndex = (U32)(ip - base); const int withinStartDistance = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex);
const U32 lowestMatchIndex = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX; const U32 lowestMatchIndex = (withinStartDistance) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX;
const BYTE* const dictBase = hc4->dictBase; const BYTE* const dictStart = hc4->dictStart;
const U32 dictIdx = hc4->lowLimit;
const BYTE* const dictEnd = dictStart + prefixIdx - dictIdx;
int const lookBackLength = (int)(ip-iLowLimit); int const lookBackLength = (int)(ip-iLowLimit);
int nbAttempts = maxNbAttempts; int nbAttempts = maxNbAttempts;
U32 matchChainPos = 0; U32 matchChainPos = 0;
@ -280,14 +284,13 @@ LZ4HC_InsertAndGetWiderMatch (
assert(matchIndex < ipIndex); assert(matchIndex < ipIndex);
if (favorDecSpeed && (ipIndex - matchIndex < 8)) { if (favorDecSpeed && (ipIndex - matchIndex < 8)) {
/* do nothing */ /* do nothing */
} else if (matchIndex >= dictLimit) { /* within current Prefix */ } else if (matchIndex >= prefixIdx) { /* within current Prefix */
const BYTE* const matchPtr = base + matchIndex; const BYTE* const matchPtr = prefixPtr + matchIndex - prefixIdx;
assert(matchPtr >= lowPrefixPtr);
assert(matchPtr < ip); assert(matchPtr < ip);
assert(longest >= 1); assert(longest >= 1);
if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) { if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) {
if (LZ4_read32(matchPtr) == pattern) { if (LZ4_read32(matchPtr) == pattern) {
int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, lowPrefixPtr) : 0; int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, prefixPtr) : 0;
matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
matchLength -= back; matchLength -= back;
if (matchLength > longest) { if (matchLength > longest) {
@ -296,24 +299,25 @@ LZ4HC_InsertAndGetWiderMatch (
*startpos = ip + back; *startpos = ip + back;
} } } } } }
} else { /* lowestMatchIndex <= matchIndex < dictLimit */ } else { /* lowestMatchIndex <= matchIndex < dictLimit */
const BYTE* const matchPtr = dictBase + matchIndex; const BYTE* const matchPtr = dictStart + (matchIndex - dictIdx);
if (LZ4_read32(matchPtr) == pattern) { assert(matchIndex >= dictIdx);
const BYTE* const dictStart = dictBase + hc4->lowLimit; if ( likely(matchIndex <= prefixIdx - 4)
&& (LZ4_read32(matchPtr) == pattern) ) {
int back = 0; int back = 0;
const BYTE* vLimit = ip + (dictLimit - matchIndex); const BYTE* vLimit = ip + (prefixIdx - matchIndex);
if (vLimit > iHighLimit) vLimit = iHighLimit; if (vLimit > iHighLimit) vLimit = iHighLimit;
matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
if ((ip+matchLength == vLimit) && (vLimit < iHighLimit)) if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))
matchLength += LZ4_count(ip+matchLength, lowPrefixPtr, iHighLimit); matchLength += LZ4_count(ip+matchLength, prefixPtr, iHighLimit);
back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0; back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0;
matchLength -= back; matchLength -= back;
if (matchLength > longest) { if (matchLength > longest) {
longest = matchLength; longest = matchLength;
*matchpos = base + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */ *matchpos = prefixPtr - prefixIdx + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */
*startpos = ip + back; *startpos = ip + back;
} } } } } }
if (chainSwap && matchLength==longest) { /* better match => select a better chain */ if (chainSwap && matchLength==longest) { /* better match => select a better chain */
assert(lookBackLength==0); /* search forward only */ assert(lookBackLength==0); /* search forward only */
if (matchIndex + (U32)longest <= ipIndex) { if (matchIndex + (U32)longest <= ipIndex) {
int const kTrigger = 4; int const kTrigger = 4;
@ -329,8 +333,7 @@ LZ4HC_InsertAndGetWiderMatch (
distanceToNextMatch = candidateDist; distanceToNextMatch = candidateDist;
matchChainPos = (U32)pos; matchChainPos = (U32)pos;
accel = 1 << kTrigger; accel = 1 << kTrigger;
} } }
}
if (distanceToNextMatch > 1) { if (distanceToNextMatch > 1) {
if (distanceToNextMatch > matchIndex) break; /* avoid overflow */ if (distanceToNextMatch > matchIndex) break; /* avoid overflow */
matchIndex -= distanceToNextMatch; matchIndex -= distanceToNextMatch;
@ -350,23 +353,24 @@ LZ4HC_InsertAndGetWiderMatch (
repeat = rep_not; repeat = rep_not;
} } } }
if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex) if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex)
&& LZ4HC_protectDictEnd(dictLimit, matchCandidateIdx) ) { && LZ4HC_protectDictEnd(prefixIdx, matchCandidateIdx) ) {
const int extDict = matchCandidateIdx < dictLimit; const int extDict = matchCandidateIdx < prefixIdx;
const BYTE* const matchPtr = (extDict ? dictBase : base) + matchCandidateIdx; const BYTE* const matchPtr = (extDict ? dictStart - dictIdx : prefixPtr - prefixIdx) + matchCandidateIdx;
if (LZ4_read32(matchPtr) == pattern) { /* good candidate */ if (LZ4_read32(matchPtr) == pattern) { /* good candidate */
const BYTE* const dictStart = dictBase + hc4->lowLimit; const BYTE* const iLimit = extDict ? dictEnd : iHighLimit;
const BYTE* const iLimit = extDict ? dictBase + dictLimit : iHighLimit;
size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern); size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern);
if (extDict && matchPtr + forwardPatternLength == iLimit) { if (extDict && matchPtr + forwardPatternLength == iLimit) {
U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern); U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern);
forwardPatternLength += LZ4HC_countPattern(lowPrefixPtr, iHighLimit, rotatedPattern); forwardPatternLength += LZ4HC_countPattern(prefixPtr, iHighLimit, rotatedPattern);
} }
{ const BYTE* const lowestMatchPtr = extDict ? dictStart : lowPrefixPtr; { const BYTE* const lowestMatchPtr = extDict ? dictStart : prefixPtr;
size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern); size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern);
size_t currentSegmentLength; size_t currentSegmentLength;
if (!extDict && matchPtr - backLength == lowPrefixPtr && hc4->lowLimit < dictLimit) { if (!extDict
&& matchPtr - backLength == prefixPtr
&& dictIdx < prefixIdx) {
U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern); U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern);
backLength += LZ4HC_reverseCountPattern(dictBase + dictLimit, dictStart, rotatedPattern); backLength += LZ4HC_reverseCountPattern(dictEnd, dictStart, rotatedPattern);
} }
/* Limit backLength not go further than lowestMatchIndex */ /* Limit backLength not go further than lowestMatchIndex */
backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex); backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex);
@ -376,28 +380,28 @@ LZ4HC_InsertAndGetWiderMatch (
if ( (currentSegmentLength >= srcPatternLength) /* current pattern segment large enough to contain full srcPatternLength */ if ( (currentSegmentLength >= srcPatternLength) /* current pattern segment large enough to contain full srcPatternLength */
&& (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */ && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */
U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength; /* best position, full pattern, might be followed by more match */ U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength; /* best position, full pattern, might be followed by more match */
if (LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) if (LZ4HC_protectDictEnd(prefixIdx, newMatchIndex))
matchIndex = newMatchIndex; matchIndex = newMatchIndex;
else { else {
/* Can only happen if started in the prefix */ /* Can only happen if started in the prefix */
assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);
matchIndex = dictLimit; matchIndex = prefixIdx;
} }
} else { } else {
U32 const newMatchIndex = matchCandidateIdx - (U32)backLength; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */ U32 const newMatchIndex = matchCandidateIdx - (U32)backLength; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */
if (!LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) { if (!LZ4HC_protectDictEnd(prefixIdx, newMatchIndex)) {
assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);
matchIndex = dictLimit; matchIndex = prefixIdx;
} else { } else {
matchIndex = newMatchIndex; matchIndex = newMatchIndex;
if (lookBackLength==0) { /* no back possible */ if (lookBackLength==0) { /* no back possible */
size_t const maxML = MIN(currentSegmentLength, srcPatternLength); size_t const maxML = MIN(currentSegmentLength, srcPatternLength);
if ((size_t)longest < maxML) { if ((size_t)longest < maxML) {
assert(base + matchIndex != ip); assert(prefixPtr - prefixIdx + matchIndex != ip);
if ((size_t)(ip - base) - matchIndex > LZ4_DISTANCE_MAX) break; if ((size_t)(ip - prefixPtr) + prefixIdx - matchIndex > LZ4_DISTANCE_MAX) break;
assert(maxML < 2 GB); assert(maxML < 2 GB);
longest = (int)maxML; longest = (int)maxML;
*matchpos = base + matchIndex; /* virtual pos, relative to ip, to retrieve offset */ *matchpos = prefixPtr - prefixIdx + matchIndex; /* virtual pos, relative to ip, to retrieve offset */
*startpos = ip; *startpos = ip;
} }
{ U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex); { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex);
@ -416,12 +420,12 @@ LZ4HC_InsertAndGetWiderMatch (
if ( dict == usingDictCtxHc if ( dict == usingDictCtxHc
&& nbAttempts > 0 && nbAttempts > 0
&& ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) { && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) {
size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base); size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
assert(dictEndOffset <= 1 GB); assert(dictEndOffset <= 1 GB);
matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset; matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset;
while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) { while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {
const BYTE* const matchPtr = dictCtx->base + dictMatchIndex; const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + dictMatchIndex;
if (LZ4_read32(matchPtr) == pattern) { if (LZ4_read32(matchPtr) == pattern) {
int mlt; int mlt;
@ -429,11 +433,11 @@ LZ4HC_InsertAndGetWiderMatch (
const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex); const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex);
if (vLimit > iHighLimit) vLimit = iHighLimit; if (vLimit > iHighLimit) vLimit = iHighLimit;
mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->base + dictCtx->dictLimit) : 0; back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;
mlt -= back; mlt -= back;
if (mlt > longest) { if (mlt > longest) {
longest = mlt; longest = mlt;
*matchpos = base + matchIndex + back; *matchpos = prefixPtr - prefixIdx + matchIndex + back;
*startpos = ip + back; *startpos = ip + back;
} } } }
@ -445,13 +449,13 @@ LZ4HC_InsertAndGetWiderMatch (
return longest; return longest;
} }
LZ4_FORCE_INLINE LZ4_FORCE_INLINE int
int LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */ LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */
const BYTE* const ip, const BYTE* const iLimit, const BYTE* const ip, const BYTE* const iLimit,
const BYTE** matchpos, const BYTE** matchpos,
const int maxNbAttempts, const int maxNbAttempts,
const int patternAnalysis, const int patternAnalysis,
const dictCtx_directive dict) const dictCtx_directive dict)
{ {
const BYTE* uselessPtr = ip; const BYTE* uselessPtr = ip;
/* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
@ -754,7 +758,7 @@ _last_literals:
} else { } else {
*op++ = (BYTE)(lastRunSize << ML_BITS); *op++ = (BYTE)(lastRunSize << ML_BITS);
} }
memcpy(op, anchor, lastRunSize); LZ4_memcpy(op, anchor, lastRunSize);
op += lastRunSize; op += lastRunSize;
} }
@ -887,13 +891,13 @@ LZ4HC_compress_generic_dictCtx (
limitedOutput_directive limit limitedOutput_directive limit
) )
{ {
const size_t position = (size_t)(ctx->end - ctx->base) - ctx->lowLimit; const size_t position = (size_t)(ctx->end - ctx->prefixStart) + (ctx->dictLimit - ctx->lowLimit);
assert(ctx->dictCtx != NULL); assert(ctx->dictCtx != NULL);
if (position >= 64 KB) { if (position >= 64 KB) {
ctx->dictCtx = NULL; ctx->dictCtx = NULL;
return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
} else if (position == 0 && *srcSizePtr > 4 KB) { } else if (position == 0 && *srcSizePtr > 4 KB) {
memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal)); LZ4_memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal));
LZ4HC_setExternalDict(ctx, (const BYTE *)src); LZ4HC_setExternalDict(ctx, (const BYTE *)src);
ctx->compressionLevel = (short)cLevel; ctx->compressionLevel = (short)cLevel;
return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
@ -956,13 +960,15 @@ int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int src
int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
{ {
int cSize;
#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t));
if (statePtr==NULL) return 0;
#else #else
LZ4_streamHC_t state; LZ4_streamHC_t state;
LZ4_streamHC_t* const statePtr = &state; LZ4_streamHC_t* const statePtr = &state;
#endif #endif
int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel); cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel);
#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
FREEMEM(statePtr); FREEMEM(statePtr);
#endif #endif
@ -985,6 +991,7 @@ int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* s
* Streaming Functions * Streaming Functions
**************************************/ **************************************/
/* allocation */ /* allocation */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_streamHC_t* LZ4_createStreamHC(void) LZ4_streamHC_t* LZ4_createStreamHC(void)
{ {
LZ4_streamHC_t* const state = LZ4_streamHC_t* const state =
@ -1001,13 +1008,12 @@ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr)
FREEMEM(LZ4_streamHCPtr); FREEMEM(LZ4_streamHCPtr);
return 0; return 0;
} }
#endif
LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size)
{ {
LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer; LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer;
/* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE);
DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size); DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size);
/* check conditions */ /* check conditions */
if (buffer == NULL) return NULL; if (buffer == NULL) return NULL;
@ -1033,9 +1039,13 @@ void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLev
if (LZ4_streamHCPtr->internal_donotuse.dirty) { if (LZ4_streamHCPtr->internal_donotuse.dirty) {
LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));
} else { } else {
/* preserve end - base : can trigger clearTable's threshold */ /* preserve end - prefixStart : can trigger clearTable's threshold */
LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.base; if (LZ4_streamHCPtr->internal_donotuse.end != NULL) {
LZ4_streamHCPtr->internal_donotuse.base = NULL; LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.prefixStart;
} else {
assert(LZ4_streamHCPtr->internal_donotuse.prefixStart == NULL);
}
LZ4_streamHCPtr->internal_donotuse.prefixStart = NULL;
LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL;
} }
LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);
@ -1086,14 +1096,14 @@ void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC
static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock) static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
{ {
DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock); DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock);
if (ctxPtr->end >= ctxPtr->base + ctxPtr->dictLimit + 4) if (ctxPtr->end >= ctxPtr->prefixStart + 4)
LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
/* Only one memory segment for extDict, so any previous extDict is lost at this stage */ /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->lowLimit = ctxPtr->dictLimit;
ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base); ctxPtr->dictStart = ctxPtr->prefixStart;
ctxPtr->dictBase = ctxPtr->base; ctxPtr->dictLimit += (U32)(ctxPtr->end - ctxPtr->prefixStart);
ctxPtr->base = newBlock - ctxPtr->dictLimit; ctxPtr->prefixStart = newBlock;
ctxPtr->end = newBlock; ctxPtr->end = newBlock;
ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */ ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
@ -1112,11 +1122,11 @@ LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
LZ4_streamHCPtr, src, *srcSizePtr, limit); LZ4_streamHCPtr, src, *srcSizePtr, limit);
assert(ctxPtr != NULL); assert(ctxPtr != NULL);
/* auto-init if forgotten */ /* auto-init if forgotten */
if (ctxPtr->base == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src); if (ctxPtr->prefixStart == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src);
/* Check overflow */ /* Check overflow */
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) { if ((size_t)(ctxPtr->end - ctxPtr->prefixStart) + ctxPtr->dictLimit > 2 GB) {
size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit; size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->prefixStart);
if (dictSize > 64 KB) dictSize = 64 KB; if (dictSize > 64 KB) dictSize = 64 KB;
LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize); LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
} }
@ -1127,13 +1137,16 @@ LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
/* Check overlapping input/dictionary space */ /* Check overlapping input/dictionary space */
{ const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr; { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;
const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit; const BYTE* const dictBegin = ctxPtr->dictStart;
const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit; const BYTE* const dictEnd = ctxPtr->dictStart + (ctxPtr->dictLimit - ctxPtr->lowLimit);
if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) { if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {
if (sourceEnd > dictEnd) sourceEnd = dictEnd; if (sourceEnd > dictEnd) sourceEnd = dictEnd;
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); ctxPtr->lowLimit += (U32)(sourceEnd - ctxPtr->dictStart);
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->dictStart += (U32)(sourceEnd - ctxPtr->dictStart);
} } if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) {
ctxPtr->lowLimit = ctxPtr->dictLimit;
ctxPtr->dictStart = ctxPtr->prefixStart;
} } }
return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit); return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit);
} }
@ -1161,7 +1174,7 @@ int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const ch
int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize) int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
{ {
LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse; LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit)); int const prefixSize = (int)(streamPtr->end - streamPtr->prefixStart);
DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize); DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);
assert(prefixSize >= 0); assert(prefixSize >= 0);
if (dictSize > 64 KB) dictSize = 64 KB; if (dictSize > 64 KB) dictSize = 64 KB;
@ -1169,12 +1182,13 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS
if (dictSize > prefixSize) dictSize = prefixSize; if (dictSize > prefixSize) dictSize = prefixSize;
if (safeBuffer == NULL) assert(dictSize == 0); if (safeBuffer == NULL) assert(dictSize == 0);
if (dictSize > 0) if (dictSize > 0)
memmove(safeBuffer, streamPtr->end - dictSize, dictSize); LZ4_memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
{ U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); { U32 const endIndex = (U32)(streamPtr->end - streamPtr->prefixStart) + streamPtr->dictLimit;
streamPtr->end = (const BYTE*)safeBuffer + dictSize; streamPtr->end = (const BYTE*)safeBuffer + dictSize;
streamPtr->base = streamPtr->end - endIndex; streamPtr->prefixStart = streamPtr->end - dictSize;
streamPtr->dictLimit = endIndex - (U32)dictSize; streamPtr->dictLimit = endIndex - (U32)dictSize;
streamPtr->lowLimit = endIndex - (U32)dictSize; streamPtr->lowLimit = endIndex - (U32)dictSize;
streamPtr->dictStart = streamPtr->prefixStart;
if (streamPtr->nextToUpdate < streamPtr->dictLimit) if (streamPtr->nextToUpdate < streamPtr->dictLimit)
streamPtr->nextToUpdate = streamPtr->dictLimit; streamPtr->nextToUpdate = streamPtr->dictLimit;
} }
@ -1202,7 +1216,7 @@ int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src,
/* Deprecated streaming functions */ /* Deprecated streaming functions */
int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; } int LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); }
/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t) /* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t)
* @return : 0 on success, !=0 if error */ * @return : 0 on success, !=0 if error */
@ -1214,6 +1228,7 @@ int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
return 0; return 0;
} }
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
void* LZ4_createHC (const char* inputBuffer) void* LZ4_createHC (const char* inputBuffer)
{ {
LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); LZ4_streamHC_t* const hc4 = LZ4_createStreamHC();
@ -1228,6 +1243,7 @@ int LZ4_freeHC (void* LZ4HC_Data)
FREEMEM(LZ4HC_Data); FREEMEM(LZ4HC_Data);
return 0; return 0;
} }
#endif
int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel) int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel)
{ {
@ -1241,11 +1257,11 @@ int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, c
char* LZ4_slideInputBufferHC(void* LZ4HC_Data) char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
{ {
LZ4_streamHC_t *ctx = (LZ4_streamHC_t*)LZ4HC_Data; LZ4_streamHC_t* const ctx = (LZ4_streamHC_t*)LZ4HC_Data;
const BYTE *bufferStart = ctx->internal_donotuse.base + ctx->internal_donotuse.lowLimit; const BYTE* bufferStart = ctx->internal_donotuse.prefixStart - ctx->internal_donotuse.dictLimit + ctx->internal_donotuse.lowLimit;
LZ4_resetStreamHC_fast(ctx, ctx->internal_donotuse.compressionLevel); LZ4_resetStreamHC_fast(ctx, ctx->internal_donotuse.compressionLevel);
/* avoid const char * -> char * conversion warning :( */ /* avoid const char * -> char * conversion warning :( */
return (char *)(uptrval)bufferStart; return (char*)(uptrval)bufferStart;
} }
@ -1328,7 +1344,7 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,
{ {
int retval = 0; int retval = 0;
#define TRAILING_LITERALS 3 #define TRAILING_LITERALS 3
#ifdef LZ4HC_HEAPMODE #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS)); LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS));
#else #else
LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */ LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */
@ -1346,7 +1362,7 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,
const BYTE* ovref = NULL; const BYTE* ovref = NULL;
/* init */ /* init */
#ifdef LZ4HC_HEAPMODE #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
if (opt == NULL) goto _return_label; if (opt == NULL) goto _return_label;
#endif #endif
DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity); DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity);
@ -1578,7 +1594,7 @@ _last_literals:
} else { } else {
*op++ = (BYTE)(lastRunSize << ML_BITS); *op++ = (BYTE)(lastRunSize << ML_BITS);
} }
memcpy(op, anchor, lastRunSize); LZ4_memcpy(op, anchor, lastRunSize);
op += lastRunSize; op += lastRunSize;
} }
@ -1611,7 +1627,7 @@ if (limit == fillOutput) {
goto _last_literals; goto _last_literals;
} }
_return_label: _return_label:
#ifdef LZ4HC_HEAPMODE #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
FREEMEM(opt); FREEMEM(opt);
#endif #endif
return retval; return retval;

View File

@ -1,7 +1,7 @@
/* /*
LZ4 HC - High Compression Mode of LZ4 LZ4 HC - High Compression Mode of LZ4
Header File Header File
Copyright (C) 2011-2017, Yann Collet. Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -196,14 +196,17 @@ LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, in
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1) #define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
/* Never ever use these definitions directly !
* Declare or allocate an LZ4_streamHC_t instead.
**/
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal; typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
struct LZ4HC_CCtx_internal struct LZ4HC_CCtx_internal
{ {
LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE]; LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];
LZ4_u16 chainTable[LZ4HC_MAXD]; LZ4_u16 chainTable[LZ4HC_MAXD];
const LZ4_byte* end; /* next block here to continue on current prefix */ 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* prefixStart; /* Indexes relative to this position */
const LZ4_byte* dictBase; /* alternate base for extDict */ const LZ4_byte* dictStart; /* alternate reference for extDict */
LZ4_u32 dictLimit; /* below that point, need extDict */ LZ4_u32 dictLimit; /* below that point, need extDict */
LZ4_u32 lowLimit; /* below that point, no more dict */ LZ4_u32 lowLimit; /* below that point, no more dict */
LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */ LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */
@ -214,20 +217,15 @@ struct LZ4HC_CCtx_internal
const LZ4HC_CCtx_internal* dictCtx; const LZ4HC_CCtx_internal* dictCtx;
}; };
#define LZ4_STREAMHC_MINSIZE 262200 /* static size, for inter-version compatibility */
/* Do not use these definitions directly !
* Declare or allocate an LZ4_streamHC_t instead.
*/
#define LZ4_STREAMHCSIZE 262200 /* static size, for inter-version compatibility */
#define LZ4_STREAMHCSIZE_VOIDP (LZ4_STREAMHCSIZE / sizeof(void*))
union LZ4_streamHC_u { union LZ4_streamHC_u {
void* table[LZ4_STREAMHCSIZE_VOIDP]; char minStateSize[LZ4_STREAMHC_MINSIZE];
LZ4HC_CCtx_internal internal_donotuse; LZ4HC_CCtx_internal internal_donotuse;
}; /* previously typedef'd to LZ4_streamHC_t */ }; /* previously typedef'd to LZ4_streamHC_t */
/* LZ4_streamHC_t : /* LZ4_streamHC_t :
* This structure allows static allocation of LZ4 HC streaming state. * This structure allows static allocation of LZ4 HC streaming state.
* This can be used to allocate statically, on state, or as part of a larger structure. * This can be used to allocate statically on stack, or as part of a larger structure.
* *
* Such state **must** be initialized using LZ4_initStreamHC() before first use. * Such state **must** be initialized using LZ4_initStreamHC() before first use.
* *
@ -242,7 +240,7 @@ union LZ4_streamHC_u {
* Required before first use of a statically allocated LZ4_streamHC_t. * Required before first use of a statically allocated LZ4_streamHC_t.
* Before v1.9.0 : use LZ4_resetStreamHC() instead * Before v1.9.0 : use LZ4_resetStreamHC() instead
*/ */
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size); LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);
/*-************************************ /*-************************************
@ -270,9 +268,11 @@ LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_comp
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather * LZ4_slideInputBufferHC() will truncate the history of the stream, rather
* than preserve a window-sized chunk of history. * than preserve a window-sized chunk of history.
*/ */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data); LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
#endif
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
@ -300,7 +300,7 @@ LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionL
* They should not be linked from DLL, * They should not be linked from DLL,
* as there is no guarantee of API stability yet. * as there is no guarantee of API stability yet.
* Prototypes will be promoted to "stable" status * Prototypes will be promoted to "stable" status
* after successfull usage in real-life scenarios. * after successful usage in real-life scenarios.
***************************************************/ ***************************************************/
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */ #ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
#ifndef TRACY_LZ4_HC_SLO_098092834 #ifndef TRACY_LZ4_HC_SLO_098092834