зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset cfb420e8ae50 (bug 1575293) for regressions rendering Graphite fonts which use lz4 internally. CLOSED TREE
MANUAL PUSH: Because the hook says I need to for this backout. --HG-- extra : rebase_source : dd86738d1fbc711e87354e27a89f91f5c6070a34 extra : amend_source : 59ae6c7936c9b7e0ecef72ed962f5ed41efe0b5a
This commit is contained in:
Родитель
51ae45f59c
Коммит
9098d47fe0
425
mfbt/lz4.c
425
mfbt/lz4.c
|
@ -106,7 +106,6 @@
|
|||
#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */
|
||||
#endif
|
||||
|
||||
#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */
|
||||
#include "lz4.h"
|
||||
/* see also "memory routines" below */
|
||||
|
||||
|
@ -183,60 +182,6 @@
|
|||
#define MEM_INIT(p,v,s) memset((p),(v),(s))
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common Constants
|
||||
**************************************/
|
||||
#define MINMATCH 4
|
||||
|
||||
#define WILDCOPYLENGTH 8
|
||||
#define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */
|
||||
#define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */
|
||||
#define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */
|
||||
#define FASTLOOP_SAFE_DISTANCE 64
|
||||
static const int LZ4_minLength = (MFLIMIT+1);
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define LZ4_DISTANCE_ABSOLUTE_MAX 65535
|
||||
#if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX) /* max supported by LZ4 format */
|
||||
# error "LZ4_DISTANCE_MAX is too big : must be <= 65535"
|
||||
#endif
|
||||
|
||||
#define ML_BITS 4
|
||||
#define ML_MASK ((1U<<ML_BITS)-1)
|
||||
#define RUN_BITS (8-ML_BITS)
|
||||
#define RUN_MASK ((1U<<RUN_BITS)-1)
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Error detection
|
||||
**************************************/
|
||||
#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# ifndef assert
|
||||
# define assert(condition) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */
|
||||
|
||||
#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"); \
|
||||
} }
|
||||
#else
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Types
|
||||
**************************************/
|
||||
|
@ -372,11 +317,6 @@ static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
|
|||
#ifndef LZ4_FAST_DEC_LOOP
|
||||
# if defined(__i386__) || defined(__x86_64__)
|
||||
# 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. */
|
||||
# define LZ4_FAST_DEC_LOOP 1
|
||||
# else
|
||||
# define LZ4_FAST_DEC_LOOP 0
|
||||
# endif
|
||||
|
@ -418,35 +358,29 @@ LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd)
|
|||
do { memcpy(d,s,16); 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_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);
|
||||
break;
|
||||
goto copy_loop;
|
||||
case 2:
|
||||
memcpy(v, srcPtr, 2);
|
||||
memcpy(&v[2], srcPtr, 2);
|
||||
memcpy(&v[4], &v[0], 4);
|
||||
break;
|
||||
goto copy_loop;
|
||||
case 4:
|
||||
memcpy(v, srcPtr, 4);
|
||||
memcpy(&v[4], srcPtr, 4);
|
||||
break;
|
||||
goto copy_loop;
|
||||
default:
|
||||
LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
copy_loop:
|
||||
memcpy(dstPtr, v, 8);
|
||||
dstPtr += 8;
|
||||
while (dstPtr < dstEnd) {
|
||||
|
@ -457,6 +391,63 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si
|
|||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common Constants
|
||||
**************************************/
|
||||
#define MINMATCH 4
|
||||
|
||||
#define WILDCOPYLENGTH 8
|
||||
#define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */
|
||||
#define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */
|
||||
#define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */
|
||||
#define FASTLOOP_SAFE_DISTANCE 64
|
||||
static const int LZ4_minLength = (MFLIMIT+1);
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#ifndef LZ4_DISTANCE_MAX /* can be user - defined at compile time */
|
||||
# define LZ4_DISTANCE_MAX 65535
|
||||
#endif
|
||||
|
||||
#if (LZ4_DISTANCE_MAX > 65535) /* max supported by LZ4 format */
|
||||
# error "LZ4_DISTANCE_MAX is too big : must be <= 65535"
|
||||
#endif
|
||||
|
||||
#define ML_BITS 4
|
||||
#define ML_MASK ((1U<<ML_BITS)-1)
|
||||
#define RUN_BITS (8-ML_BITS)
|
||||
#define RUN_MASK ((1U<<RUN_BITS)-1)
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Error detection
|
||||
**************************************/
|
||||
#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# ifndef assert
|
||||
# define assert(condition) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */
|
||||
|
||||
#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"); \
|
||||
} }
|
||||
#else
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common functions
|
||||
**************************************/
|
||||
|
@ -469,7 +460,7 @@ static unsigned LZ4_NbCommonBytes (reg_t val)
|
|||
_BitScanForward64( &r, (U64)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (unsigned)__builtin_ctzll((U64)val) >> 3;
|
||||
return (__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,
|
||||
|
@ -487,7 +478,7 @@ static unsigned LZ4_NbCommonBytes (reg_t val)
|
|||
_BitScanForward( &r, (U32)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (unsigned)__builtin_ctz((U32)val) >> 3;
|
||||
return (__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,
|
||||
|
@ -503,7 +494,7 @@ static unsigned LZ4_NbCommonBytes (reg_t val)
|
|||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (unsigned)__builtin_clzll((U64)val) >> 3;
|
||||
return (__builtin_clzll((U64)val) >> 3);
|
||||
# else
|
||||
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.
|
||||
|
@ -520,7 +511,7 @@ static unsigned LZ4_NbCommonBytes (reg_t val)
|
|||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (unsigned)__builtin_clz((U32)val) >> 3;
|
||||
return (__builtin_clz((U32)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
||||
|
@ -615,11 +606,9 @@ int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize);
|
||||
int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize);
|
||||
|
||||
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,
|
||||
int compressedSize, int maxOutputSize,
|
||||
const void* dictStart, size_t dictSize);
|
||||
int LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize, const void* dict, size_t dictSize);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
@ -654,18 +643,6 @@ LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tab
|
|||
return LZ4_hash4(LZ4_read32(p), tableType);
|
||||
}
|
||||
|
||||
static void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)
|
||||
{
|
||||
switch (tableType)
|
||||
{
|
||||
default: /* fallthrough */
|
||||
case clearedTable: { /* illegal! */ assert(0); return; }
|
||||
case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; }
|
||||
case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; }
|
||||
case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; }
|
||||
}
|
||||
}
|
||||
|
||||
static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)
|
||||
{
|
||||
switch (tableType)
|
||||
|
@ -726,19 +703,18 @@ static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType
|
|||
{ const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
|
||||
}
|
||||
|
||||
LZ4_FORCE_INLINE const BYTE*
|
||||
LZ4_getPosition(const BYTE* p,
|
||||
const void* tableBase, tableType_t tableType,
|
||||
const BYTE* srcBase)
|
||||
LZ4_FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p,
|
||||
const void* tableBase, tableType_t tableType,
|
||||
const BYTE* srcBase)
|
||||
{
|
||||
U32 const h = LZ4_hashPosition(p, tableType);
|
||||
return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
|
||||
}
|
||||
|
||||
LZ4_FORCE_INLINE void
|
||||
LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
||||
const int inputSize,
|
||||
const tableType_t tableType) {
|
||||
LZ4_FORCE_INLINE void 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.
|
||||
*/
|
||||
|
@ -753,10 +729,9 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx,
|
|||
* out if it's safe to leave as is or whether it needs to be reset.
|
||||
*/
|
||||
if (cctx->tableType != clearedTable) {
|
||||
assert(inputSize >= 0);
|
||||
if (cctx->tableType != tableType
|
||||
|| ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU)
|
||||
|| ((tableType == byU32) && cctx->currentOffset > 1 GB)
|
||||
|| (tableType == byU16 && cctx->currentOffset + inputSize >= 0xFFFFU)
|
||||
|| (tableType == byU32 && cctx->currentOffset > 1 GB)
|
||||
|| tableType == byPtr
|
||||
|| inputSize >= 4 KB)
|
||||
{
|
||||
|
@ -836,9 +811,9 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|||
DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType);
|
||||
/* 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 (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);
|
||||
|
||||
|
@ -866,7 +841,6 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
BYTE* token;
|
||||
const BYTE* filledIp;
|
||||
|
||||
/* Find a match */
|
||||
if (tableType == byPtr) {
|
||||
|
@ -935,14 +909,10 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|||
forwardH = LZ4_hashPosition(forwardIp, tableType);
|
||||
LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
|
||||
|
||||
DEBUGLOG(7, "candidate at pos=%u (offset=%u \n", matchIndex, current - matchIndex);
|
||||
if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } /* match outside of valid area */
|
||||
if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) continue; /* match outside of valid area */
|
||||
assert(matchIndex < current);
|
||||
if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX))
|
||||
&& (matchIndex+LZ4_DISTANCE_MAX < current)) {
|
||||
continue;
|
||||
} /* too far */
|
||||
assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* match now expected within distance */
|
||||
if ((tableType != byU16) && (matchIndex+LZ4_DISTANCE_MAX < current)) continue; /* too far */
|
||||
if (tableType == byU16) assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* too_far presumed impossible with byU16 */
|
||||
|
||||
if (LZ4_read32(match) == LZ4_read32(ip)) {
|
||||
if (maybe_extMem) offset = current - matchIndex;
|
||||
|
@ -953,16 +923,15 @@ LZ4_FORCE_INLINE int LZ4_compress_generic(
|
|||
}
|
||||
|
||||
/* Catch up */
|
||||
filledIp = ip;
|
||||
while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
|
||||
|
||||
/* Encode Literals */
|
||||
{ unsigned const litLength = (unsigned)(ip - anchor);
|
||||
token = op++;
|
||||
if ((outputDirective == limitedOutput) && /* Check output buffer overflow */
|
||||
(unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) {
|
||||
(unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) )
|
||||
return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
|
||||
}
|
||||
|
||||
if ((outputDirective == fillOutput) &&
|
||||
(unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) {
|
||||
op--;
|
||||
|
@ -1033,26 +1002,12 @@ _next_match:
|
|||
}
|
||||
|
||||
if ((outputDirective) && /* Check output buffer overflow */
|
||||
(unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) {
|
||||
(unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) {
|
||||
if (outputDirective == fillOutput) {
|
||||
/* Match description too long : reduce it */
|
||||
U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255;
|
||||
U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 2 - 1 - LASTLITERALS) * 255;
|
||||
ip -= matchCode - newMatchCode;
|
||||
assert(newMatchCode < matchCode);
|
||||
matchCode = newMatchCode;
|
||||
if (unlikely(ip <= filledIp)) {
|
||||
/* We have already filled up to filledIp so if ip ends up less than filledIp
|
||||
* we have positions in the hash table beyond the current position. This is
|
||||
* a problem if we reuse the hash table. So we have to remove these positions
|
||||
* from the hash table.
|
||||
*/
|
||||
const BYTE* ptr;
|
||||
DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip));
|
||||
for (ptr = ip; ptr <= filledIp; ++ptr) {
|
||||
U32 const h = LZ4_hashPosition(ptr, tableType);
|
||||
LZ4_clearHash(h, cctx->hashTable, tableType);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(outputDirective == limitedOutput);
|
||||
return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
|
||||
|
@ -1072,8 +1027,6 @@ _next_match:
|
|||
} else
|
||||
*token += (BYTE)(matchCode);
|
||||
}
|
||||
/* Ensure we have enough space for the last literals. */
|
||||
assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit));
|
||||
|
||||
anchor = ip;
|
||||
|
||||
|
@ -1123,7 +1076,7 @@ _next_match:
|
|||
LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
|
||||
assert(matchIndex < current);
|
||||
if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1)
|
||||
&& (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current))
|
||||
&& ((tableType==byU16) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current))
|
||||
&& (LZ4_read32(match) == LZ4_read32(ip)) ) {
|
||||
token=op++;
|
||||
*token=0;
|
||||
|
@ -1190,7 +1143,7 @@ int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int
|
|||
return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
|
||||
}
|
||||
} else {
|
||||
if (inputSize < LZ4_64Klimit) {
|
||||
if (inputSize < LZ4_64Klimit) {;
|
||||
return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||
} else {
|
||||
const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;
|
||||
|
@ -1353,12 +1306,12 @@ static size_t LZ4_stream_t_alignment(void)
|
|||
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; }
|
||||
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 */
|
||||
if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) return NULL; /* alignment check */
|
||||
#endif
|
||||
MEM_INIT(buffer, 0, sizeof(LZ4_stream_t));
|
||||
return (LZ4_stream_t*)buffer;
|
||||
|
@ -1408,18 +1361,18 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
|
|||
* there are only valid offsets in the window, which allows an optimization
|
||||
* in LZ4_compress_fast_continue() where it uses noDictIssue even when the
|
||||
* dictionary isn't a full 64k. */
|
||||
|
||||
if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
|
||||
base = dictEnd - 64 KB - dict->currentOffset;
|
||||
dict->dictionary = p;
|
||||
dict->dictSize = (U32)(dictEnd - p);
|
||||
dict->currentOffset += 64 KB;
|
||||
dict->tableType = tableType;
|
||||
|
||||
if (dictSize < (int)HASH_UNIT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
|
||||
base = dictEnd - dict->currentOffset;
|
||||
dict->dictionary = p;
|
||||
dict->dictSize = (U32)(dictEnd - p);
|
||||
dict->tableType = tableType;
|
||||
|
||||
while (p <= dictEnd-HASH_UNIT) {
|
||||
LZ4_putPosition(p, dict->hashTable, tableType, base);
|
||||
p+=3;
|
||||
|
@ -1428,37 +1381,26 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
|
|||
return (int)dict->dictSize;
|
||||
}
|
||||
|
||||
void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream) {
|
||||
const LZ4_stream_t_internal* dictCtx = dictionaryStream == NULL ? NULL :
|
||||
&(dictionaryStream->internal_donotuse);
|
||||
|
||||
DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)",
|
||||
workingStream, dictionaryStream,
|
||||
dictCtx != NULL ? dictCtx->dictSize : 0);
|
||||
|
||||
void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream) {
|
||||
/* 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);
|
||||
LZ4_resetStream_fast(working_stream);
|
||||
|
||||
if (dictCtx != NULL) {
|
||||
if (dictionary_stream != NULL) {
|
||||
/* If the current offset is zero, we will never look in the
|
||||
* external dictionary context, since there is no value a table
|
||||
* entry can take that indicate a miss. In that case, we need
|
||||
* to bump the offset to something non-zero.
|
||||
*/
|
||||
if (workingStream->internal_donotuse.currentOffset == 0) {
|
||||
workingStream->internal_donotuse.currentOffset = 64 KB;
|
||||
}
|
||||
|
||||
/* Don't actually attach an empty dictionary.
|
||||
*/
|
||||
if (dictCtx->dictSize == 0) {
|
||||
dictCtx = NULL;
|
||||
if (working_stream->internal_donotuse.currentOffset == 0) {
|
||||
working_stream->internal_donotuse.currentOffset = 64 KB;
|
||||
}
|
||||
working_stream->internal_donotuse.dictCtx = &(dictionary_stream->internal_donotuse);
|
||||
} else {
|
||||
working_stream->internal_donotuse.dictCtx = NULL;
|
||||
}
|
||||
workingStream->internal_donotuse.dictCtx = dictCtx;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1493,7 +1435,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
|
|||
|
||||
DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i)", inputSize);
|
||||
|
||||
if (streamPtr->dirty) { return 0; } /* Uninitialized structure detected */
|
||||
if (streamPtr->dirty) return 0; /* Uninitialized structure detected */
|
||||
LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */
|
||||
if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
|
||||
|
||||
|
@ -1590,8 +1532,8 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
|||
LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
|
||||
const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
|
||||
|
||||
if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
|
||||
if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
|
||||
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);
|
||||
|
||||
|
@ -1665,7 +1607,7 @@ LZ4_decompress_generic(
|
|||
const size_t dictSize /* note : = 0 if noDict */
|
||||
)
|
||||
{
|
||||
if (src == NULL) { return -1; }
|
||||
if (src == NULL) return -1;
|
||||
|
||||
{ const BYTE* ip = (const BYTE*) src;
|
||||
const BYTE* const iend = ip + srcSize;
|
||||
|
@ -1694,13 +1636,9 @@ LZ4_decompress_generic(
|
|||
|
||||
/* Special cases */
|
||||
assert(lowPrefix <= op);
|
||||
if ((endOnInput) && (unlikely(outputSize==0))) {
|
||||
/* Empty output buffer */
|
||||
if (partialDecoding) return 0;
|
||||
return ((srcSize==1) && (*ip==0)) ? 0 : -1;
|
||||
}
|
||||
if ((!endOnInput) && (unlikely(outputSize==0))) { return (*ip==0 ? 1 : -1); }
|
||||
if ((endOnInput) && unlikely(srcSize==0)) { return -1; }
|
||||
if ((endOnInput) && (unlikely(outputSize==0))) return ((srcSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
|
||||
if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0 ? 1 : -1);
|
||||
if ((endOnInput) && unlikely(srcSize==0)) return -1;
|
||||
|
||||
/* Currently the fast loop shows a regression on qualcomm arm chips. */
|
||||
#if LZ4_FAST_DEC_LOOP
|
||||
|
@ -1713,7 +1651,7 @@ LZ4_decompress_generic(
|
|||
while (1) {
|
||||
/* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */
|
||||
assert(oend - op >= FASTLOOP_SAFE_DISTANCE);
|
||||
if (endOnInput) { assert(ip < iend); }
|
||||
if (endOnInput) assert(ip < iend);
|
||||
token = *ip++;
|
||||
length = token >> ML_BITS; /* literal length */
|
||||
|
||||
|
@ -1723,18 +1661,18 @@ LZ4_decompress_generic(
|
|||
if (length == RUN_MASK) {
|
||||
variable_length_error error = ok;
|
||||
length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, 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 */
|
||||
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 */
|
||||
|
||||
/* copy literals */
|
||||
cpy = op+length;
|
||||
LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
|
||||
if (endOnInput) { /* LZ4_decompress_safe() */
|
||||
if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }
|
||||
if ((cpy>oend-32) || (ip+length>iend-32)) goto safe_literal_copy;
|
||||
LZ4_wildCopy32(op, ip, cpy);
|
||||
} else { /* LZ4_decompress_fast() */
|
||||
if (cpy>oend-8) { goto safe_literal_copy; }
|
||||
if (cpy>oend-8) goto safe_literal_copy;
|
||||
LZ4_wildCopy8(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time :
|
||||
* it doesn't know input length, and only relies on end-of-block properties */
|
||||
}
|
||||
|
@ -1744,14 +1682,14 @@ LZ4_decompress_generic(
|
|||
if (endOnInput) { /* LZ4_decompress_safe() */
|
||||
DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length);
|
||||
/* 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; }
|
||||
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);
|
||||
} 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); }
|
||||
if (length > 8) memcpy(op+8, ip+8, 8);
|
||||
}
|
||||
ip += length; op = cpy;
|
||||
}
|
||||
|
@ -1759,17 +1697,17 @@ LZ4_decompress_generic(
|
|||
/* get offset */
|
||||
offset = LZ4_readLE16(ip); ip+=2;
|
||||
match = op - offset;
|
||||
assert(match <= op);
|
||||
|
||||
/* get matchlength */
|
||||
length = token & ML_MASK;
|
||||
|
||||
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */
|
||||
|
||||
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; }
|
||||
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */
|
||||
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) {
|
||||
goto safe_match_copy;
|
||||
|
@ -1781,12 +1719,8 @@ LZ4_decompress_generic(
|
|||
}
|
||||
|
||||
/* Fastpath check: Avoids a branch in LZ4_wildCopy32 if true */
|
||||
if ((dict == withPrefix64k) || (match >= lowPrefix)) {
|
||||
if (!(dict == usingExtDict) || (match >= lowPrefix)) {
|
||||
if (offset >= 8) {
|
||||
assert(match >= lowPrefix);
|
||||
assert(match <= op);
|
||||
assert(op + 18 <= oend);
|
||||
|
||||
memcpy(op, match, 8);
|
||||
memcpy(op+8, match+8, 8);
|
||||
memcpy(op+16, match+16, 2);
|
||||
|
@ -1794,15 +1728,12 @@ LZ4_decompress_generic(
|
|||
continue;
|
||||
} } }
|
||||
|
||||
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 */
|
||||
} else {
|
||||
goto _output_error; /* end-of-block condition violated */
|
||||
} }
|
||||
if (partialDecoding) length = MIN(length, (size_t)(oend-op));
|
||||
else goto _output_error; /* doesn't respect parsing restriction */
|
||||
}
|
||||
|
||||
if (length <= (size_t)(lowPrefix-match)) {
|
||||
/* match fits entirely within external dictionary : just copy */
|
||||
|
@ -1817,7 +1748,7 @@ LZ4_decompress_generic(
|
|||
if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */
|
||||
BYTE* const endOfMatch = op + restSize;
|
||||
const BYTE* copyFrom = lowPrefix;
|
||||
while (op < endOfMatch) { *op++ = *copyFrom++; }
|
||||
while (op < endOfMatch) *op++ = *copyFrom++;
|
||||
} else {
|
||||
memcpy(op, lowPrefix, restSize);
|
||||
op += restSize;
|
||||
|
@ -1890,11 +1821,11 @@ LZ4_decompress_generic(
|
|||
|
||||
/* decode literal length */
|
||||
if (length == RUN_MASK) {
|
||||
variable_length_error error = ok;
|
||||
length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, 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 */
|
||||
variable_length_error error = ok;
|
||||
length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, 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 */
|
||||
}
|
||||
|
||||
/* copy literals */
|
||||
|
@ -1906,50 +1837,21 @@ LZ4_decompress_generic(
|
|||
if ( ((endOnInput) && ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) )
|
||||
|| ((!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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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 (cpy > oend) {
|
||||
cpy = oend;
|
||||
assert(op<=oend);
|
||||
length = (size_t)(oend-op);
|
||||
}
|
||||
assert(ip+length <= iend);
|
||||
if (cpy > oend) { cpy = oend; assert(op<=oend); length = (size_t)(oend-op); } /* Partial decoding : stop in the middle of literal segment */
|
||||
if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
|
||||
} 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).
|
||||
*/
|
||||
if ((!endOnInput) && (cpy != oend)) { goto _output_error; }
|
||||
/* 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) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
|
||||
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
|
||||
}
|
||||
memmove(op, ip, length); /* supports overlapping memory regions, which only matters for in-place decompression scenarios */
|
||||
memcpy(op, ip, length);
|
||||
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.
|
||||
*/
|
||||
if (!partialDecoding || (cpy == oend) || (ip == iend)) {
|
||||
if (!partialDecoding || (cpy == oend)) {
|
||||
/* Necessarily EOF, due to parsing restrictions */
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
LZ4_wildCopy8(op, ip, cpy); /* may overwrite up to WILDCOPYLENGTH beyond cpy */
|
||||
ip += length; op = cpy;
|
||||
|
@ -1963,6 +1865,13 @@ LZ4_decompress_generic(
|
|||
length = token & ML_MASK;
|
||||
|
||||
_copy_match:
|
||||
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */
|
||||
if (!partialDecoding) {
|
||||
assert(oend > op);
|
||||
assert(oend - op >= 4);
|
||||
LZ4_write32(op, 0); /* silence an msan warning when offset==0; costs <1%; */
|
||||
} /* note : when partialDecoding, there is no guarantee that at least 4 bytes remain available in output buffer */
|
||||
|
||||
if (length == ML_MASK) {
|
||||
variable_length_error error = ok;
|
||||
length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);
|
||||
|
@ -1974,7 +1883,6 @@ LZ4_decompress_generic(
|
|||
#if LZ4_FAST_DEC_LOOP
|
||||
safe_match_copy:
|
||||
#endif
|
||||
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)) {
|
||||
|
@ -2002,7 +1910,6 @@ LZ4_decompress_generic(
|
|||
} }
|
||||
continue;
|
||||
}
|
||||
assert(match >= lowPrefix);
|
||||
|
||||
/* copy match within block */
|
||||
cpy = op + length;
|
||||
|
@ -2014,17 +1921,16 @@ LZ4_decompress_generic(
|
|||
const BYTE* const matchEnd = match + mlen;
|
||||
BYTE* const copyEnd = op + mlen;
|
||||
if (matchEnd > op) { /* overlap copy */
|
||||
while (op < copyEnd) { *op++ = *match++; }
|
||||
while (op < copyEnd) *op++ = *match++;
|
||||
} else {
|
||||
memcpy(op, match, mlen);
|
||||
}
|
||||
op = copyEnd;
|
||||
if (op == oend) { break; }
|
||||
if (op==oend) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unlikely(offset<8)) {
|
||||
LZ4_write32(op, 0); /* silence msan warning when offset==0 */
|
||||
op[0] = match[0];
|
||||
op[1] = match[1];
|
||||
op[2] = match[2];
|
||||
|
@ -2040,26 +1946,25 @@ LZ4_decompress_generic(
|
|||
|
||||
if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {
|
||||
BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1);
|
||||
if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
|
||||
if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
|
||||
if (op < oCopyLimit) {
|
||||
LZ4_wildCopy8(op, match, oCopyLimit);
|
||||
match += oCopyLimit - op;
|
||||
op = oCopyLimit;
|
||||
}
|
||||
while (op < cpy) { *op++ = *match++; }
|
||||
while (op < cpy) *op++ = *match++;
|
||||
} else {
|
||||
memcpy(op, match, 8);
|
||||
if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); }
|
||||
if (length > 16) LZ4_wildCopy8(op+8, match+8, cpy);
|
||||
}
|
||||
op = cpy; /* wildcopy correction */
|
||||
}
|
||||
|
||||
/* end of decoding */
|
||||
if (endOnInput) {
|
||||
if (endOnInput)
|
||||
return (int) (((char*)op)-dst); /* Nb of output bytes decoded */
|
||||
} else {
|
||||
else
|
||||
return (int) (((const char*)ip)-src); /* Nb of input bytes read */
|
||||
}
|
||||
|
||||
/* Overflow error detected */
|
||||
_output_error:
|
||||
|
@ -2174,7 +2079,7 @@ LZ4_streamDecode_t* LZ4_createStreamDecode(void)
|
|||
|
||||
int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
|
||||
{
|
||||
if (LZ4_stream == NULL) { return 0; } /* support free on NULL */
|
||||
if (LZ4_stream == NULL) return 0; /* support free on NULL */
|
||||
FREEMEM(LZ4_stream);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2309,22 +2214,18 @@ int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressed
|
|||
if (dictSize==0)
|
||||
return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);
|
||||
if (dictStart+dictSize == dest) {
|
||||
if (dictSize >= 64 KB - 1) {
|
||||
if (dictSize >= 64 KB - 1)
|
||||
return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);
|
||||
}
|
||||
assert(dictSize >= 0);
|
||||
return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize);
|
||||
return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, dictSize);
|
||||
}
|
||||
assert(dictSize >= 0);
|
||||
return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize);
|
||||
return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, dictSize);
|
||||
}
|
||||
|
||||
int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
if (dictSize==0 || dictStart+dictSize == dest)
|
||||
return LZ4_decompress_fast(source, dest, originalSize);
|
||||
assert(dictSize >= 0);
|
||||
return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize);
|
||||
return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, dictSize);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2336,9 +2237,9 @@ int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, in
|
|||
{
|
||||
return LZ4_compress_default(source, dest, inputSize, maxOutputSize);
|
||||
}
|
||||
int LZ4_compress(const char* src, char* dest, int srcSize)
|
||||
int LZ4_compress(const char* source, char* dest, int inputSize)
|
||||
{
|
||||
return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize));
|
||||
return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize));
|
||||
}
|
||||
int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize)
|
||||
{
|
||||
|
|
142
mfbt/lz4.h
142
mfbt/lz4.h
|
@ -46,7 +46,7 @@ extern "C" {
|
|||
/**
|
||||
Introduction
|
||||
|
||||
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
|
||||
LZ4 is lossless compression algorithm, providing compression speed at 500 MB/s per core,
|
||||
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||
|
||||
|
@ -58,19 +58,16 @@ extern "C" {
|
|||
- unbounded multiple steps (described as Streaming compression)
|
||||
|
||||
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
|
||||
Decompressing such a compressed block requires additional metadata.
|
||||
Exact metadata depends on exact decompression function.
|
||||
For the typical case of LZ4_decompress_safe(),
|
||||
metadata includes block's compressed size, and maximum bound of decompressed size.
|
||||
Decompressing a block requires additional metadata, such as its compressed size.
|
||||
Each application is free to encode and pass such metadata in whichever way it wants.
|
||||
|
||||
lz4.h only handle blocks, it can not generate Frames.
|
||||
|
||||
Blocks are different from Frames (doc/lz4_Frame_format.md).
|
||||
Frames bundle both blocks and metadata in a specified manner.
|
||||
Embedding metadata is required for compressed data to be self-contained and portable.
|
||||
This are required for compressed data to be self-contained and portable.
|
||||
Frame format is delivered through a companion API, declared in lz4frame.h.
|
||||
The `lz4` CLI can only manage frames.
|
||||
Note that the `lz4` CLI can only manage frames.
|
||||
*/
|
||||
|
||||
/*^***************************************************************
|
||||
|
@ -100,7 +97,7 @@ extern "C" {
|
|||
/*------ 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 1 /* for tweaks, bug-fixes, or development */
|
||||
|
||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||
|
||||
|
@ -132,35 +129,29 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string;
|
|||
* Simple Functions
|
||||
**************************************/
|
||||
/*! LZ4_compress_default() :
|
||||
* Compresses 'srcSize' bytes from buffer 'src'
|
||||
* into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||
* It also runs faster, so it's a recommended setting.
|
||||
* If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||
* compression stops *immediately*, and the function result is zero.
|
||||
* In which case, 'dst' content is undefined (invalid).
|
||||
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||
* dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||
* or 0 if compression fails
|
||||
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||
*/
|
||||
Compresses 'srcSize' bytes from buffer 'src'
|
||||
into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||
Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
In which case, 'dst' content is undefined (invalid).
|
||||
srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||
dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||
@return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||
or 0 if compression fails
|
||||
Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
||||
|
||||
/*! LZ4_decompress_safe() :
|
||||
* compressedSize : is the exact complete size of the compressed block.
|
||||
* dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.
|
||||
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
* Note 1 : This function is protected against malicious data packets :
|
||||
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
|
||||
* even if the compressed block is maliciously modified to order the decoder to do these actions.
|
||||
* In such case, the decoder stops immediately, and considers the compressed block malformed.
|
||||
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
|
||||
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
|
||||
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
|
||||
*/
|
||||
compressedSize : is the exact complete size of the compressed block.
|
||||
dstCapacity : is the size of destination buffer, which must be already allocated.
|
||||
@return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
Note : This function is protected against malicious data packets (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
||||
|
||||
|
||||
|
@ -397,8 +388,6 @@ LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecod
|
|||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
|
||||
|
||||
#endif /* LZ4_H_2983827168210 */
|
||||
|
||||
|
||||
/*^*************************************
|
||||
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||
|
@ -424,17 +413,14 @@ LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int sr
|
|||
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||
|
||||
#ifndef LZ4_STATIC_3504398509
|
||||
#define LZ4_STATIC_3504398509
|
||||
|
||||
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
|
||||
#define LZ4LIB_STATIC_API LZ4LIB_API
|
||||
#else
|
||||
#define LZ4LIB_STATIC_API
|
||||
#endif
|
||||
|
||||
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||
|
||||
|
||||
/*! LZ4_compress_fast_extState_fastReset() :
|
||||
* A variant of LZ4_compress_fast_extState().
|
||||
|
@ -476,75 +462,8 @@ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const c
|
|||
*/
|
||||
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
|
||||
|
||||
|
||||
/*! In-place compression and decompression
|
||||
*
|
||||
* It's possible to have input and output sharing the same buffer,
|
||||
* for highly contrained memory environments.
|
||||
* In both cases, it requires input to lay at the end 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--------------------------------->|
|
||||
* |<-----------compressed data--------->|
|
||||
* |<-----------decompressed size------------------>|
|
||||
* |<----margin---->|
|
||||
*
|
||||
* This technique is more useful for decompression,
|
||||
* since decompressed size is typically larger,
|
||||
* and margin is short.
|
||||
*
|
||||
* In-place decompression will work inside any buffer
|
||||
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
|
||||
* This presumes that decompressedSize > compressedSize.
|
||||
* Otherwise, it means compression actually expanded data,
|
||||
* and it would be more efficient to store such data with a flag indicating it's not compressed.
|
||||
* This can happen when data is not compressible (already compressed, or encrypted).
|
||||
*
|
||||
* For in-place compression, margin is larger, as it must be able to cope with both
|
||||
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
|
||||
* and data expansion, which can happen when input is not compressible.
|
||||
* As a consequence, buffer size requirements are much higher,
|
||||
* and memory savings offered by in-place compression are more limited.
|
||||
*
|
||||
* There are ways to limit this cost for compression :
|
||||
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
|
||||
* Note that it is a compile-time constant, so all compressions will apply this limit.
|
||||
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
|
||||
* so it's a reasonable trick when inputs are known to be small.
|
||||
* - Require the compressor to deliver a "maximum compressed size".
|
||||
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
|
||||
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
|
||||
* in which case, the return code will be 0 (zero).
|
||||
* The caller must be ready for these cases to happen,
|
||||
* and typically design a backup scheme to send data uncompressed.
|
||||
* The combination of both techniques can significantly reduce
|
||||
* the amount of margin required for in-place compression.
|
||||
*
|
||||
* In-place compression can work in any buffer
|
||||
* which size is >= (maxCompressedSize)
|
||||
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
|
||||
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
|
||||
* so it's possible to reduce memory requirements by playing with them.
|
||||
*/
|
||||
|
||||
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
|
||||
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
|
||||
|
||||
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
|
||||
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
|
||||
#endif
|
||||
|
||||
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
|
||||
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
|
||||
|
||||
#endif /* LZ4_STATIC_3504398509 */
|
||||
#endif /* LZ4_STATIC_LINKING_ONLY */
|
||||
|
||||
|
||||
|
||||
#ifndef LZ4_H_98237428734687
|
||||
#define LZ4_H_98237428734687
|
||||
|
||||
/*-************************************************************
|
||||
* PRIVATE DEFINITIONS
|
||||
|
@ -648,7 +567,6 @@ union LZ4_streamDecode_u {
|
|||
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
|
@ -683,8 +601,8 @@ union LZ4_streamDecode_u {
|
|||
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
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_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, 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);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
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);
|
||||
|
@ -756,7 +674,7 @@ LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int or
|
|||
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
|
||||
#endif /* LZ4_H_98237428734687 */
|
||||
#endif /* LZ4_H_2983827168210 */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
Загрузка…
Ссылка в новой задаче