changed dictionary format

This commit is contained in:
Yann Collet
2016-01-28 00:21:13 +01:00
parent 1c8e194297
commit fb810d6053
8 changed files with 437 additions and 445 deletions
+3
View File
@@ -1,3 +1,6 @@
v0.5.0
Changed streaming & dictionary API
v0.4.7 v0.4.7
Improved : small compression speed improvement in HC mode Improved : small compression speed improvement in HC mode
Changed : `zstd_decompress.c` has ZSTD_LEGACY_SUPPORT to 0 by default Changed : `zstd_decompress.c` has ZSTD_LEGACY_SUPPORT to 0 by default
+45 -103
View File
@@ -425,10 +425,7 @@ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
} }
static short FSE_abs(short a) static short FSE_abs(short a) { return a<0 ? -a : a; }
{
return a<0 ? -a : a;
}
static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize, static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
@@ -457,14 +454,11 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
threshold = tableSize; threshold = tableSize;
nbBits = tableLog+1; nbBits = tableLog+1;
while (remaining>1) /* stops at 1 */ while (remaining>1) { /* stops at 1 */
{ if (previous0) {
if (previous0)
{
unsigned start = charnum; unsigned start = charnum;
while (!normalizedCounter[charnum]) charnum++; while (!normalizedCounter[charnum]) charnum++;
while (charnum >= start+24) while (charnum >= start+24) {
{
start+=24; start+=24;
bitStream += 0xFFFFU << bitCount; bitStream += 0xFFFFU << bitCount;
if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
@@ -473,24 +467,21 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
out+=2; out+=2;
bitStream>>=16; bitStream>>=16;
} }
while (charnum >= start+3) while (charnum >= start+3) {
{
start+=3; start+=3;
bitStream += 3 << bitCount; bitStream += 3 << bitCount;
bitCount += 2; bitCount += 2;
} }
bitStream += (charnum-start) << bitCount; bitStream += (charnum-start) << bitCount;
bitCount += 2; bitCount += 2;
if (bitCount>16) if (bitCount>16) {
{
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE)bitStream; out[0] = (BYTE)bitStream;
out[1] = (BYTE)(bitStream>>8); out[1] = (BYTE)(bitStream>>8);
out += 2; out += 2;
bitStream >>= 16; bitStream >>= 16;
bitCount -= 16; bitCount -= 16;
} } }
}
{ {
short count = normalizedCounter[charnum++]; short count = normalizedCounter[charnum++];
const short max = (short)((2*threshold-1)-remaining); const short max = (short)((2*threshold-1)-remaining);
@@ -504,8 +495,7 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
previous0 = (count==1); previous0 = (count==1);
while (remaining<threshold) nbBits--, threshold>>=1; while (remaining<threshold) nbBits--, threshold>>=1;
} }
if (bitCount>16) if (bitCount>16) {
{
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE)bitStream; out[0] = (BYTE)bitStream;
out[1] = (BYTE)(bitStream>>8); out[1] = (BYTE)(bitStream>>8);
@@ -564,27 +554,19 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
threshold = 1<<nbBits; threshold = 1<<nbBits;
nbBits++; nbBits++;
while ((remaining>1) && (charnum<=*maxSVPtr)) while ((remaining>1) && (charnum<=*maxSVPtr)) {
{ if (previous0) {
if (previous0)
{
unsigned n0 = charnum; unsigned n0 = charnum;
while ((bitStream & 0xFFFF) == 0xFFFF) while ((bitStream & 0xFFFF) == 0xFFFF) {
{
n0+=24; n0+=24;
if (ip < iend-5) if (ip < iend-5) {
{
ip+=2; ip+=2;
bitStream = MEM_readLE32(ip) >> bitCount; bitStream = MEM_readLE32(ip) >> bitCount;
} } else {
else
{
bitStream >>= 16; bitStream >>= 16;
bitCount+=16; bitCount+=16;
} } }
} while ((bitStream & 3) == 3) {
while ((bitStream & 3) == 3)
{
n0+=3; n0+=3;
bitStream>>=2; bitStream>>=2;
bitCount+=2; bitCount+=2;
@@ -593,8 +575,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
bitCount += 2; bitCount += 2;
if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
while (charnum < n0) normalizedCounter[charnum++] = 0; while (charnum < n0) normalizedCounter[charnum++] = 0;
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
{
ip += bitCount>>3; ip += bitCount>>3;
bitCount &= 7; bitCount &= 7;
bitStream = MEM_readLE32(ip) >> bitCount; bitStream = MEM_readLE32(ip) >> bitCount;
@@ -606,13 +587,10 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
const short max = (short)((2*threshold-1)-remaining); const short max = (short)((2*threshold-1)-remaining);
short count; short count;
if ((bitStream & (threshold-1)) < (U32)max) if ((bitStream & (threshold-1)) < (U32)max) {
{
count = (short)(bitStream & (threshold-1)); count = (short)(bitStream & (threshold-1));
bitCount += nbBits-1; bitCount += nbBits-1;
} } else {
else
{
count = (short)(bitStream & (2*threshold-1)); count = (short)(bitStream & (2*threshold-1));
if (count >= threshold) count -= max; if (count >= threshold) count -= max;
bitCount += nbBits; bitCount += nbBits;
@@ -622,27 +600,20 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
remaining -= FSE_abs(count); remaining -= FSE_abs(count);
normalizedCounter[charnum++] = count; normalizedCounter[charnum++] = count;
previous0 = !count; previous0 = !count;
while (remaining < threshold) while (remaining < threshold) {
{
nbBits--; nbBits--;
threshold >>= 1; threshold >>= 1;
} }
{ if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))
{
ip += bitCount>>3; ip += bitCount>>3;
bitCount &= 7; bitCount &= 7;
} } else {
else
{
bitCount -= (int)(8 * (iend - 4 - ip)); bitCount -= (int)(8 * (iend - 4 - ip));
ip = iend - 4; ip = iend - 4;
} }
bitStream = MEM_readLE32(ip) >> (bitCount & 31); bitStream = MEM_readLE32(ip) >> (bitCount & 31);
} } }
}
}
if (remaining != 1) return ERROR(GENERIC); if (remaining != 1) return ERROR(GENERIC);
*maxSVPtr = charnum-1; *maxSVPtr = charnum-1;
@@ -723,22 +694,18 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
U32 lowThreshold = (U32)(total >> tableLog); U32 lowThreshold = (U32)(total >> tableLog);
U32 lowOne = (U32)((total * 3) >> (tableLog + 1)); U32 lowOne = (U32)((total * 3) >> (tableLog + 1));
for (s=0; s<=maxSymbolValue; s++) for (s=0; s<=maxSymbolValue; s++) {
{ if (count[s] == 0) {
if (count[s] == 0)
{
norm[s]=0; norm[s]=0;
continue; continue;
} }
if (count[s] <= lowThreshold) if (count[s] <= lowThreshold) {
{
norm[s] = -1; norm[s] = -1;
distributed++; distributed++;
total -= count[s]; total -= count[s];
continue; continue;
} }
if (count[s] <= lowOne) if (count[s] <= lowOne) {
{
norm[s] = 1; norm[s] = 1;
distributed++; distributed++;
total -= count[s]; total -= count[s];
@@ -748,25 +715,20 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
} }
ToDistribute = (1 << tableLog) - distributed; ToDistribute = (1 << tableLog) - distributed;
if ((total / ToDistribute) > lowOne) if ((total / ToDistribute) > lowOne) {
{
/* risk of rounding to zero */ /* risk of rounding to zero */
lowOne = (U32)((total * 3) / (ToDistribute * 2)); lowOne = (U32)((total * 3) / (ToDistribute * 2));
for (s=0; s<=maxSymbolValue; s++) for (s=0; s<=maxSymbolValue; s++) {
{ if ((norm[s] == -2) && (count[s] <= lowOne)) {
if ((norm[s] == -2) && (count[s] <= lowOne))
{
norm[s] = 1; norm[s] = 1;
distributed++; distributed++;
total -= count[s]; total -= count[s];
continue; continue;
} } }
}
ToDistribute = (1 << tableLog) - distributed; ToDistribute = (1 << tableLog) - distributed;
} }
if (distributed == maxSymbolValue+1) if (distributed == maxSymbolValue+1) {
{
/* all values are pretty poor; /* all values are pretty poor;
probably incompressible data (should have already been detected); probably incompressible data (should have already been detected);
find max, then give all remaining points to max */ find max, then give all remaining points to max */
@@ -782,10 +744,8 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
U64 const mid = (1ULL << (vStepLog-1)) - 1; U64 const mid = (1ULL << (vStepLog-1)) - 1;
U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */
U64 tmpTotal = mid; U64 tmpTotal = mid;
for (s=0; s<=maxSymbolValue; s++) for (s=0; s<=maxSymbolValue; s++) {
{ if (norm[s]==-2) {
if (norm[s]==-2)
{
U64 end = tmpTotal + (count[s] * rStep); U64 end = tmpTotal + (count[s] * rStep);
U32 sStart = (U32)(tmpTotal >> vStepLog); U32 sStart = (U32)(tmpTotal >> vStepLog);
U32 sEnd = (U32)(end >> vStepLog); U32 sEnd = (U32)(end >> vStepLog);
@@ -794,9 +754,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
return ERROR(GENERIC); return ERROR(GENERIC);
norm[s] = (short)weight; norm[s] = (short)weight;
tmpTotal = end; tmpTotal = end;
} } } }
}
}
return 0; return 0;
} }
@@ -809,7 +767,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
/* Sanity checks */ /* Sanity checks */
if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */ if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */
if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC); /* Unsupported size */ if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
{ {
@@ -823,38 +781,23 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
short largestP=0; short largestP=0;
U32 lowThreshold = (U32)(total >> tableLog); U32 lowThreshold = (U32)(total >> tableLog);
for (s=0; s<=maxSymbolValue; s++) for (s=0; s<=maxSymbolValue; s++) {
{ if (count[s] == total) return 0; /* rle special case */
if (count[s] == total) return 0; if (count[s] == 0) { normalizedCounter[s]=0; continue; }
if (count[s] == 0) if (count[s] <= lowThreshold) {
{
normalizedCounter[s]=0;
continue;
}
if (count[s] <= lowThreshold)
{
normalizedCounter[s] = -1; normalizedCounter[s] = -1;
stillToDistribute--; stillToDistribute--;
} } else {
else
{
short proba = (short)((count[s]*step) >> scale); short proba = (short)((count[s]*step) >> scale);
if (proba<8) if (proba<8) {
{
U64 restToBeat = vStep * rtbTable[proba]; U64 restToBeat = vStep * rtbTable[proba];
proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat; proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;
} }
if (proba > largestP) if (proba > largestP) largestP=proba, largest=s;
{
largestP=proba;
largest=s;
}
normalizedCounter[s] = proba; normalizedCounter[s] = proba;
stillToDistribute -= proba; stillToDistribute -= proba;
} } }
} if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {
if (-stillToDistribute >= (normalizedCounter[largest] >> 1))
{
/* corner case, need another normalization method */ /* corner case, need another normalization method */
size_t errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); size_t errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);
if (FSE_isError(errorCode)) return errorCode; if (FSE_isError(errorCode)) return errorCode;
@@ -904,8 +847,7 @@ size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits)
tableU16[s] = (U16)(tableSize + s); tableU16[s] = (U16)(tableSize + s);
/* Build Symbol Transformation Table */ /* Build Symbol Transformation Table */
for (s=0; s<=maxSymbolValue; s++) for (s=0; s<=maxSymbolValue; s++) {
{
symbolTT[s].deltaNbBits = nbBits << 16; symbolTT[s].deltaNbBits = nbBits << 16;
symbolTT[s].deltaFindState = s-1; symbolTT[s].deltaFindState = s-1;
} }
+1 -1
View File
@@ -46,7 +46,7 @@ extern "C" {
#include <stddef.h> /* size_t, ptrdiff_t */ #include <stddef.h> /* size_t, ptrdiff_t */
/* ***************************************** /*-****************************************
* FSE simple functions * FSE simple functions
******************************************/ ******************************************/
size_t FSE_compress(void* dst, size_t maxDstSize, size_t FSE_compress(void* dst, size_t maxDstSize,
+1 -2
View File
@@ -223,8 +223,7 @@ static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t
/* ***************************************** /* *****************************************
* Implementation of inlined functions * Implementation of inlined functions
*******************************************/ *******************************************/
typedef struct typedef struct {
{
int deltaFindState; int deltaFindState;
U32 deltaNbBits; U32 deltaNbBits;
} FSE_symbolCompressionTransform; /* total 8 bytes */ } FSE_symbolCompressionTransform; /* total 8 bytes */
+202 -251
View File
@@ -126,7 +126,10 @@ struct ZSTD_CCtx_s
U32* hashTable; U32* hashTable;
U32* contentTable; U32* contentTable;
HUF_CElt* hufTable; HUF_CElt* hufTable;
U32 flagHufTable; U32 flagStaticTables;
FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
FSE_CTable matchlengthCTable [FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
}; };
@@ -158,8 +161,7 @@ void ZSTD_validateParams(ZSTD_parameters* params)
if (params->windowLog < ZSTD_WINDOWLOG_MIN) params->windowLog = ZSTD_WINDOWLOG_MIN; if (params->windowLog < ZSTD_WINDOWLOG_MIN) params->windowLog = ZSTD_WINDOWLOG_MIN;
/* correct params, to use less memory */ /* correct params, to use less memory */
if ((params->srcSize > 0) && (params->srcSize < (1<<ZSTD_WINDOWLOG_MAX))) if ((params->srcSize > 0) && (params->srcSize < (1<<ZSTD_WINDOWLOG_MAX))) {
{
U32 srcLog = ZSTD_highbit((U32)(params->srcSize)-1) + 1; U32 srcLog = ZSTD_highbit((U32)(params->srcSize)-1) + 1;
if (params->windowLog > srcLog) params->windowLog = srcLog; if (params->windowLog > srcLog) params->windowLog = srcLog;
} }
@@ -188,8 +190,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog; const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog;
const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32); const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32);
const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize); const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize);
if (zc->workSpaceSize < neededSpace) if (zc->workSpaceSize < neededSpace) {
{
free(zc->workSpace); free(zc->workSpace);
zc->workSpace = malloc(neededSpace); zc->workSpace = malloc(neededSpace);
if (zc->workSpace == NULL) return ERROR(memory_allocation); if (zc->workSpace == NULL) return ERROR(memory_allocation);
@@ -200,7 +201,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog); zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog);
zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog); zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog);
zc->hufTable = (HUF_CElt*)zc->seqStore.buffer; zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
zc->flagHufTable = 0; zc->flagStaticTables = 0;
zc->seqStore.buffer = (U32*)(zc->seqStore.buffer) + 256; zc->seqStore.buffer = (U32*)(zc->seqStore.buffer) + 256;
} }
@@ -253,9 +254,14 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
dstCCtx->dictLimit = srcCCtx->dictLimit; dstCCtx->dictLimit = srcCCtx->dictLimit;
dstCCtx->lowLimit = srcCCtx->lowLimit; dstCCtx->lowLimit = srcCCtx->lowLimit;
dstCCtx->flagHufTable = srcCCtx->flagHufTable; /* copy entropy tables */
if (dstCCtx->flagHufTable) dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
if (dstCCtx->flagStaticTables) {
memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4); memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
}
return 0; return 0;
} }
@@ -271,8 +277,7 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
U32* table32 = zc->hashTable; U32* table32 = zc->hashTable;
U32 index; U32 index;
for (index=0 ; index < tableSpaceU32 ; index++) for (index=0 ; index < tableSpaceU32 ; index++) {
{
if (table32[index] < reducerValue) table32[index] = 0; if (table32[index] < reducerValue) table32[index] = 0;
else table32[index] -= reducerValue; else table32[index] -= reducerValue;
} }
@@ -338,15 +343,35 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
1.2.1) Huff0 block, using sizes from header 1.2.1) Huff0 block, using sizes from header
See Huff0 format See Huff0 format
1.2.2) Raw content 1.2.2) Huff0 block, using prepared table
1.2.3) single byte 1.2.3) Raw content
1.2.4) _usingDTable variant ? 1.2.4) single byte
2) Sequences section 2) Sequences section
TO DO
- Nb Sequences : 2 bytes, little endian
- Control Token : 1 byte (see below)
- Dumps Length : 1 or 2 bytes (depending on control token)
- Dumps : as stated by dumps length
- Literal Lengths FSE table (as needed depending on encoding method)
- Offset Codes FSE table (as needed depending on encoding method)
- Match Lengths FSE table (as needed depending on encoding method)
2.1) Control Token
8 bits, divided as :
0-1 : dumpsLength
2-3 : MatchLength, FSE encoding method
4-5 : Offset Codes, FSE encoding method
6-7 : Literal Lengths, FSE encoding method
FSE encoding method :
FSE_ENCODING_RAW : uncompressed; no header
FSE_ENCODING_RLE : single repeated value; header 1 byte
FSE_ENCODING_STATIC : use prepared table; no header
FSE_ENCODING_DYNAMIC : read NCount
*/ */
size_t ZSTD_noCompressBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize) size_t ZSTD_noCompressBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
@@ -399,7 +424,7 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t maxDstSize, const
BYTE* const ostart = (BYTE* const)dst; BYTE* const ostart = (BYTE* const)dst;
U32 flSize = 1 + (srcSize>31) + (srcSize>4095); U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
(void)maxDstSize; /* maxDstSize guaranteed to be >=4, hence large enough ? */ (void)maxDstSize; /* maxDstSize guaranteed to be >=4, hence large enough */
switch(flSize) switch(flSize)
{ {
@@ -438,14 +463,11 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
if (maxDstSize < 4) return ERROR(dstSize_tooSmall); /* not enough space for compression */ if (maxDstSize < 4) return ERROR(dstSize_tooSmall); /* not enough space for compression */
if (zc->flagHufTable && (lhSize==3)) if (zc->flagStaticTables && (lhSize==3)) {
{
hType = IS_PCH; hType = IS_PCH;
singleStream = 1; singleStream = 1;
clitSize = HUF_compress1X_usingCTable(ostart+lhSize, maxDstSize-lhSize, src, srcSize, zc->hufTable); clitSize = HUF_compress1X_usingCTable(ostart+lhSize, maxDstSize-lhSize, src, srcSize, zc->hufTable);
} } else {
else
{
clitSize = singleStream ? HUF_compress1X(ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12) clitSize = singleStream ? HUF_compress1X(ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12)
: HUF_compress2 (ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12); : HUF_compress2 (ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12);
} }
@@ -491,11 +513,10 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
U32 count[MaxSeq+1]; U32 count[MaxSeq+1];
S16 norm[MaxSeq+1]; S16 norm[MaxSeq+1];
size_t mostFrequent; size_t mostFrequent;
U32 max = 255; U32 max;
U32 tableLog = 11; FSE_CTable* CTable_LitLength = zc->litlengthCTable;
U32 CTable_LitLength [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL )]; FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
U32 CTable_OffsetBits [FSE_CTABLE_SIZE_U32(OffFSELog,MaxOff)]; FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
U32 CTable_MatchLength[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML )];
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
const BYTE* const op_lit_start = seqStorePtr->litStart; const BYTE* const op_lit_start = seqStorePtr->litStart;
const BYTE* const llTable = seqStorePtr->litLengthStart; const BYTE* const llTable = seqStorePtr->litLengthStart;
@@ -516,7 +537,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
{ {
size_t cSize; size_t cSize;
size_t litSize = seqStorePtr->lit - op_lit_start; size_t litSize = seqStorePtr->lit - op_lit_start;
const size_t minLitSize = zc->flagHufTable ? 6 : LITERAL_NOENTROPY; const size_t minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
if (litSize <= minLitSize) if (litSize <= minLitSize)
cSize = ZSTD_noCompressLiterals(op, maxDstSize, op_lit_start, litSize); cSize = ZSTD_noCompressLiterals(op, maxDstSize, op_lit_start, litSize);
@@ -535,14 +556,11 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
/* dumps : contains too large lengths */ /* dumps : contains too large lengths */
{ {
size_t dumpsLength = seqStorePtr->dumps - seqStorePtr->dumpsStart; size_t dumpsLength = seqStorePtr->dumps - seqStorePtr->dumpsStart;
if (dumpsLength < 512) if (dumpsLength < 512) {
{
op[0] = (BYTE)(dumpsLength >> 8); op[0] = (BYTE)(dumpsLength >> 8);
op[1] = (BYTE)(dumpsLength); op[1] = (BYTE)(dumpsLength);
op += 2; op += 2;
} } else {
else
{
op[0] = 2; op[0] = 2;
op[1] = (BYTE)(dumpsLength>>8); op[1] = (BYTE)(dumpsLength>>8);
op[2] = (BYTE)(dumpsLength); op[2] = (BYTE)(dumpsLength);
@@ -553,94 +571,86 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
op += dumpsLength; op += dumpsLength;
} }
#define MIN_SEQ_FOR_DYNAMIC_FSE 64
#define MAX_SEQ_FOR_STATIC_FSE 1000
/* CTable for Literal Lengths */ /* CTable for Literal Lengths */
max = MaxLL; max = MaxLL;
mostFrequent = FSE_countFast(count, &max, seqStorePtr->litLengthStart, nbSeq); mostFrequent = FSE_countFast(count, &max, seqStorePtr->litLengthStart, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2)) if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
{
*op++ = *(seqStorePtr->litLengthStart); *op++ = *(seqStorePtr->litLengthStart);
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
LLtype = bt_rle; LLtype = FSE_ENCODING_RLE;
} } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (LLbits-1)))) LLtype = FSE_ENCODING_STATIC;
{ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LLbits-1)))) {
FSE_buildCTable_raw(CTable_LitLength, LLbits); FSE_buildCTable_raw(CTable_LitLength, LLbits);
LLtype = bt_raw; LLtype = FSE_ENCODING_RAW;
} } else {
else
{
size_t NCountSize; size_t NCountSize;
tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max); U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max); FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */ NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC); if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize; op += NCountSize;
FSE_buildCTable(CTable_LitLength, norm, max, tableLog); FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
LLtype = bt_compressed; LLtype = FSE_ENCODING_DYNAMIC;
} }
/* CTable for Offsets codes */ /* CTable for Offset codes */
{ { /* create Offset codes */
/* create Offset codes */ size_t i; for (i=0; i<nbSeq; i++) {
size_t i;
max = MaxOff;
for (i=0; i<nbSeq; i++)
{
offCodeTable[i] = (BYTE)ZSTD_highbit(offsetTable[i]) + 1; offCodeTable[i] = (BYTE)ZSTD_highbit(offsetTable[i]) + 1;
if (offsetTable[i]==0) offCodeTable[i]=0; if (offsetTable[i]==0) offCodeTable[i]=0;
} }
mostFrequent = FSE_countFast(count, &max, offCodeTable, nbSeq);
} }
if ((mostFrequent == nbSeq) && (nbSeq > 2)) max = MaxOff;
{ mostFrequent = FSE_countFast(count, &max, offCodeTable, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
*op++ = *offCodeTable; *op++ = *offCodeTable;
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
Offtype = bt_rle; Offtype = FSE_ENCODING_RLE;
} } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (Offbits-1)))) Offtype = FSE_ENCODING_STATIC;
{ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
FSE_buildCTable_raw(CTable_OffsetBits, Offbits); FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
Offtype = bt_raw; Offtype = FSE_ENCODING_RAW;
} } else {
else
{
size_t NCountSize; size_t NCountSize;
tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max); U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max); FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */ NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC); if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize; op += NCountSize;
FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog); FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
Offtype = bt_compressed; Offtype = FSE_ENCODING_DYNAMIC;
} }
/* CTable for MatchLengths */ /* CTable for MatchLengths */
max = MaxML; max = MaxML;
mostFrequent = FSE_countFast(count, &max, seqStorePtr->matchLengthStart, nbSeq); mostFrequent = FSE_countFast(count, &max, seqStorePtr->matchLengthStart, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2)) if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
{
*op++ = *seqStorePtr->matchLengthStart; *op++ = *seqStorePtr->matchLengthStart;
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
MLtype = bt_rle; MLtype = FSE_ENCODING_RLE;
} } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (MLbits-1)))) MLtype = FSE_ENCODING_STATIC;
{ } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (MLbits-1)))) {
FSE_buildCTable_raw(CTable_MatchLength, MLbits); FSE_buildCTable_raw(CTable_MatchLength, MLbits);
MLtype = bt_raw; MLtype = FSE_ENCODING_RAW;
} } else {
else
{
size_t NCountSize; size_t NCountSize;
tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max); U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max); FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */ NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC); if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize; op += NCountSize;
FSE_buildCTable(CTable_MatchLength, norm, max, tableLog); FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
MLtype = bt_compressed; MLtype = FSE_ENCODING_DYNAMIC;
} }
seqHead[0] += (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); seqHead[0] += (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
zc->flagStaticTables = 0;
/* Encoding Sequences */ /* Encoding Sequences */
{ {
@@ -657,14 +667,13 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
FSE_initCState(&stateOffsetBits, CTable_OffsetBits); FSE_initCState(&stateOffsetBits, CTable_OffsetBits);
FSE_initCState(&stateLitLength, CTable_LitLength); FSE_initCState(&stateLitLength, CTable_LitLength);
for (i=(int)nbSeq-1; i>=0; i--) for (i=(int)nbSeq-1; i>=0; i--) {
{ BYTE mlCode = mlTable[i];
BYTE matchLength = mlTable[i];
U32 offset = offsetTable[i]; U32 offset = offsetTable[i];
BYTE offCode = offCodeTable[i]; /* 32b*/ /* 64b*/ BYTE offCode = offCodeTable[i]; /* 32b*/ /* 64b*/
U32 nbBits = (offCode-1) * (!!offCode); U32 nbBits = (offCode-1) * (!!offCode);
BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/ BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/
FSE_encodeSymbol(&blockStream, &stateMatchLength, matchLength); /* 17 */ /* 17 */ FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 17 */ /* 17 */
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */ if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */ BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */ if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
@@ -699,7 +708,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
#if 0 #if 0
static const BYTE* g_start = NULL; static const BYTE* g_start = NULL;
if (g_start==NULL) g_start = literals; if (g_start==NULL) g_start = literals;
if (literals - g_start == 8695) //if (literals - g_start == 8695)
printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n", printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
(U32)(literals - g_start), (U32)litLength, (U32)matchCode+4, (U32)offsetCode); (U32)(literals - g_start), (U32)litLength, (U32)matchCode+4, (U32)offsetCode);
#endif #endif
@@ -709,34 +718,28 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
seqStorePtr->lit += litLength; seqStorePtr->lit += litLength;
/* literal Length */ /* literal Length */
if (litLength >= MaxLL) if (litLength >= MaxLL) {
{
*(seqStorePtr->litLength++) = MaxLL; *(seqStorePtr->litLength++) = MaxLL;
if (litLength<255 + MaxLL) if (litLength<255 + MaxLL) {
*(seqStorePtr->dumps++) = (BYTE)(litLength - MaxLL); *(seqStorePtr->dumps++) = (BYTE)(litLength - MaxLL);
else } else {
{
*(seqStorePtr->dumps++) = 255; *(seqStorePtr->dumps++) = 255;
MEM_writeLE32(seqStorePtr->dumps, (U32)litLength); seqStorePtr->dumps += 3; MEM_writeLE32(seqStorePtr->dumps, (U32)litLength); seqStorePtr->dumps += 3;
} } }
}
else *(seqStorePtr->litLength++) = (BYTE)litLength; else *(seqStorePtr->litLength++) = (BYTE)litLength;
/* match offset */ /* match offset */
*(seqStorePtr->offset++) = (U32)offsetCode; *(seqStorePtr->offset++) = (U32)offsetCode;
/* match Length */ /* match Length */
if (matchCode >= MaxML) if (matchCode >= MaxML) {
{
*(seqStorePtr->matchLength++) = MaxML; *(seqStorePtr->matchLength++) = MaxML;
if (matchCode < 255+MaxML) if (matchCode < 255+MaxML) {
*(seqStorePtr->dumps++) = (BYTE)(matchCode - MaxML); *(seqStorePtr->dumps++) = (BYTE)(matchCode - MaxML);
else } else {
{
*(seqStorePtr->dumps++) = 255; *(seqStorePtr->dumps++) = 255;
MEM_writeLE32(seqStorePtr->dumps, (U32)matchCode); seqStorePtr->dumps += 3; MEM_writeLE32(seqStorePtr->dumps, (U32)matchCode); seqStorePtr->dumps += 3;
} } }
}
else *(seqStorePtr->matchLength++) = (BYTE)matchCode; else *(seqStorePtr->matchLength++) = (BYTE)matchCode;
} }
@@ -841,8 +844,7 @@ static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLim
{ {
const BYTE* const pStart = pIn; const BYTE* const pStart = pIn;
while ((pIn<pInLimit-(sizeof(size_t)-1))) while ((pIn<pInLimit-(sizeof(size_t)-1))) {
{
size_t diff = ZSTD_read_ARCH(pMatch) ^ ZSTD_read_ARCH(pIn); size_t diff = ZSTD_read_ARCH(pMatch) ^ ZSTD_read_ARCH(pIn);
if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; } if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
pIn += ZSTD_NbCommonBytes(diff); pIn += ZSTD_NbCommonBytes(diff);
@@ -917,8 +919,7 @@ static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
const BYTE* ip = base + zc->nextToUpdate; const BYTE* ip = base + zc->nextToUpdate;
const BYTE* const iend = (const BYTE*) end; const BYTE* const iend = (const BYTE*) end;
while(ip <= iend) while(ip <= iend) {
{
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
ip += FILLHASHSTEP; ip += FILLHASHSTEP;
} }
@@ -947,8 +948,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
/* init */ /* init */
ZSTD_resetSeqStore(seqStorePtr); ZSTD_resetSeqStore(seqStorePtr);
if (ip < lowest+4) if (ip < lowest+4) {
{
hashTable[ZSTD_hashPtr(lowest+1, hBits, mls)] = lowIndex+1; hashTable[ZSTD_hashPtr(lowest+1, hBits, mls)] = lowIndex+1;
hashTable[ZSTD_hashPtr(lowest+2, hBits, mls)] = lowIndex+2; hashTable[ZSTD_hashPtr(lowest+2, hBits, mls)] = lowIndex+2;
hashTable[ZSTD_hashPtr(lowest+3, hBits, mls)] = lowIndex+3; hashTable[ZSTD_hashPtr(lowest+3, hBits, mls)] = lowIndex+3;
@@ -956,8 +956,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
} }
/* Main Search Loop */ /* Main Search Loop */
while (ip < ilimit) /* < instead of <=, because repcode check at (ip+1) */ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
{
size_t mlCode; size_t mlCode;
size_t offset; size_t offset;
const size_t h = ZSTD_hashPtr(ip, hBits, mls); const size_t h = ZSTD_hashPtr(ip, hBits, mls);
@@ -966,17 +965,13 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
const U32 current = (U32)(ip-base); const U32 current = (U32)(ip-base);
hashTable[h] = current; /* update hash table */ hashTable[h] = current; /* update hash table */
if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) /* note : by construction, offset_1 <= current */ if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) { /* note : by construction, offset_1 <= current */
{
mlCode = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend); mlCode = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend);
ip++; ip++;
offset = 0; offset = 0;
} } else {
else
{
if ( (matchIndex <= lowIndex) || if ( (matchIndex <= lowIndex) ||
(MEM_read32(match) != MEM_read32(ip)) ) (MEM_read32(match) != MEM_read32(ip)) ) {
{
ip += ((ip-anchor) >> g_searchStrength) + 1; ip += ((ip-anchor) >> g_searchStrength) + 1;
continue; continue;
} }
@@ -992,15 +987,13 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
ip += mlCode + MINMATCH; ip += mlCode + MINMATCH;
anchor = ip; anchor = ip;
if (ip <= ilimit) if (ip <= ilimit) {
{
/* Fill Table */ /* Fill Table */
hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base); hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
/* check immediate repcode */ /* check immediate repcode */
while ( (ip <= ilimit) while ( (ip <= ilimit)
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
{
/* store sequence */ /* store sequence */
size_t rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); size_t rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
size_t tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */ size_t tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
@@ -1009,9 +1002,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
ip += rlCode+MINMATCH; ip += rlCode+MINMATCH;
anchor = ip; anchor = ip;
continue; /* faster when present ... (?) */ continue; /* faster when present ... (?) */
} } } }
}
}
/* Last Literals */ /* Last Literals */
{ {
@@ -1067,18 +1058,15 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
/* init */ /* init */
ZSTD_resetSeqStore(seqStorePtr); ZSTD_resetSeqStore(seqStorePtr);
{
/* skip first 4 positions to avoid read overflow during repcode match check */ /* skip first 4 positions to avoid read overflow during repcode match check */
hashTable[ZSTD_hashPtr(ip+0, hBits, mls)] = (U32)(ip-base+0); hashTable[ZSTD_hashPtr(ip+0, hBits, mls)] = (U32)(ip-base+0);
hashTable[ZSTD_hashPtr(ip+1, hBits, mls)] = (U32)(ip-base+1); hashTable[ZSTD_hashPtr(ip+1, hBits, mls)] = (U32)(ip-base+1);
hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip-base+2); hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip-base+2);
hashTable[ZSTD_hashPtr(ip+3, hBits, mls)] = (U32)(ip-base+3); hashTable[ZSTD_hashPtr(ip+3, hBits, mls)] = (U32)(ip-base+3);
ip += 4; ip += 4;
}
/* Main Search Loop */ /* Main Search Loop */
while (ip < ilimit) /* < instead of <=, because (ip+1) */ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
{
const size_t h = ZSTD_hashPtr(ip, hBits, mls); const size_t h = ZSTD_hashPtr(ip, hBits, mls);
const U32 matchIndex = hashTable[h]; const U32 matchIndex = hashTable[h];
const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base; const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
@@ -1092,15 +1080,12 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
hashTable[h] = current; /* update hash table */ hashTable[h] = current; /* update hash table */
if ( ((repIndex <= dictLimit-4) || (repIndex >= dictLimit)) if ( ((repIndex <= dictLimit-4) || (repIndex >= dictLimit))
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
{
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr); mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
ip++; ip++;
offset = 0; offset = 0;
} } else {
else
{
if ( (matchIndex < lowLimit) || if ( (matchIndex < lowLimit) ||
(MEM_read32(match) != MEM_read32(ip)) ) (MEM_read32(match) != MEM_read32(ip)) )
{ ip += ((ip-anchor) >> g_searchStrength) + 1; continue; } { ip += ((ip-anchor) >> g_searchStrength) + 1; continue; }
@@ -1112,28 +1097,24 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
offset = current - matchIndex; offset = current - matchIndex;
offset_2 = offset_1; offset_2 = offset_1;
offset_1 = offset; offset_1 = offset;
} } }
}
/* found a match : store it */ /* found a match : store it */
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode); ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
ip += mlCode + MINMATCH; ip += mlCode + MINMATCH;
anchor = ip; anchor = ip;
if (ip <= ilimit) if (ip <= ilimit) {
{
/* Fill Table */ /* Fill Table */
hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base); hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
/* check immediate repcode */ /* check immediate repcode */
while (ip <= ilimit) while (ip <= ilimit) {
{
U32 current2 = (U32)(ip-base); U32 current2 = (U32)(ip-base);
const U32 repIndex2 = current2 - offset_2; const U32 repIndex2 = current2 - offset_2;
const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2; const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit)) if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
{
const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend; const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
size_t repLength2 = ZSTD_count_2segments(ip+MINMATCH, repMatch2+MINMATCH, iend, repEnd2, lowPrefixPtr); size_t repLength2 = ZSTD_count_2segments(ip+MINMATCH, repMatch2+MINMATCH, iend, repEnd2, lowPrefixPtr);
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
@@ -1144,9 +1125,7 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
continue; continue;
} }
break; break;
} } } }
}
}
/* Last Literals */ /* Last Literals */
{ {
@@ -1213,14 +1192,13 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
hashTable[h] = current; /* Update Hash Table */ hashTable[h] = current; /* Update Hash Table */
while (nbCompares-- && (matchIndex > windowLow)) while (nbCompares-- && (matchIndex > windowLow)) {
{
U32* nextPtr = bt + 2*(matchIndex & btMask); U32* nextPtr = bt + 2*(matchIndex & btMask);
const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
if (matchIndex == predictedSmall) if (matchIndex == predictedSmall) {
{ /* no need to check length, result known */ /* no need to check length, result known */
*smallerPtr = matchIndex; *smallerPtr = matchIndex;
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
@@ -1229,8 +1207,7 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
continue; continue;
} }
if (matchIndex == predictedLarge) if (matchIndex == predictedLarge) {
{
*largerPtr = matchIndex; *largerPtr = matchIndex;
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
largerPtr = nextPtr; largerPtr = nextPtr;
@@ -1239,14 +1216,11 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
continue; continue;
} }
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
{
match = base + matchIndex; match = base + matchIndex;
if (match[matchLength] == ip[matchLength]) if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1; matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
} } else {
else
{
match = dictBase + matchIndex; match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
if (matchIndex+matchLength >= dictLimit) if (matchIndex+matchLength >= dictLimit)
@@ -1259,25 +1233,21 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
if (match[matchLength] < ip[matchLength]) /* necessarily within correct buffer */ if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
{
/* match is smaller than current */ /* match is smaller than current */
*smallerPtr = matchIndex; /* update smaller idx */ *smallerPtr = matchIndex; /* update smaller idx */
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
} } else {
else
{
/* match is larger than current */ /* match is larger than current */
*largerPtr = matchIndex; *largerPtr = matchIndex;
commonLengthLarger = matchLength; commonLengthLarger = matchLength;
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
largerPtr = nextPtr; largerPtr = nextPtr;
matchIndex = nextPtr[0]; matchIndex = nextPtr[0];
} } }
}
*smallerPtr = *largerPtr = 0; *smallerPtr = *largerPtr = 0;
return (matchEndIdx > current + 8) ? matchEndIdx - current - 8 : 1; return (matchEndIdx > current + 8) ? matchEndIdx - current - 8 : 1;
@@ -1326,28 +1296,23 @@ size_t ZSTD_insertBtAndFindBestMatch (
hashTable[h] = current; /* Update Hash Table */ hashTable[h] = current; /* Update Hash Table */
while (nbCompares-- && (matchIndex > windowLow)) while (nbCompares-- && (matchIndex > windowLow)) {
{
U32* nextPtr = bt + 2*(matchIndex & btMask); U32* nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match; const BYTE* match;
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
{
match = base + matchIndex; match = base + matchIndex;
if (match[matchLength] == ip[matchLength]) if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1; matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
} } else {
else
{
match = dictBase + matchIndex; match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
if (matchIndex+matchLength >= dictLimit) if (matchIndex+matchLength >= dictLimit)
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
} }
if (matchLength > bestLength) if (matchLength > bestLength) {
{
if (matchLength > matchEndIdx - matchIndex) if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength; matchEndIdx = matchIndex + (U32)matchLength;
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) ) if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) )
@@ -1356,17 +1321,14 @@ size_t ZSTD_insertBtAndFindBestMatch (
break; /* drop, to guarantee consistency (miss a little bit of compression) */ break; /* drop, to guarantee consistency (miss a little bit of compression) */
} }
if (match[matchLength] < ip[matchLength]) if (match[matchLength] < ip[matchLength]) {
{
/* match is smaller than current */ /* match is smaller than current */
*smallerPtr = matchIndex; /* update smaller idx */ *smallerPtr = matchIndex; /* update smaller idx */
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
} } else {
else
{
/* match is larger than current */ /* match is larger than current */
*largerPtr = matchIndex; *largerPtr = matchIndex;
commonLengthLarger = matchLength; commonLengthLarger = matchLength;
@@ -1472,8 +1434,7 @@ static U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
const U32 target = (U32)(ip - base); const U32 target = (U32)(ip - base);
U32 idx = zc->nextToUpdate; U32 idx = zc->nextToUpdate;
while(idx < target) while(idx < target) {
{
size_t h = ZSTD_hashPtr(base+idx, hashLog, mls); size_t h = ZSTD_hashPtr(base+idx, hashLog, mls);
NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
hashTable[h] = idx; hashTable[h] = idx;
@@ -1511,18 +1472,14 @@ size_t ZSTD_HcFindBestMatch_generic (
/* HC4 match finder */ /* HC4 match finder */
matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls); matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
while ((matchIndex>lowLimit) && (nbAttempts)) while ((matchIndex>lowLimit) && (nbAttempts)) {
{
size_t currentMl=0; size_t currentMl=0;
nbAttempts--; nbAttempts--;
if ((!extDict) || matchIndex >= dictLimit) if ((!extDict) || matchIndex >= dictLimit) {
{
match = base + matchIndex; match = base + matchIndex;
if (match[ml] == ip[ml]) /* potentially better */ if (match[ml] == ip[ml]) /* potentially better */
currentMl = ZSTD_count(ip, match, iLimit); currentMl = ZSTD_count(ip, match, iLimit);
} } else {
else
{
match = dictBase + matchIndex; match = dictBase + matchIndex;
if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH; currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
@@ -1601,15 +1558,13 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE; if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
/* Match Loop */ /* Match Loop */
while (ip < ilimit) while (ip < ilimit) {
{
size_t matchLength=0; size_t matchLength=0;
size_t offset=0; size_t offset=0;
const BYTE* start=ip+1; const BYTE* start=ip+1;
/* check repCode */ /* check repCode */
if (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1)) if (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1)) {
{
/* repcode : we take it */ /* repcode : we take it */
matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend) + MINMATCH; matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend) + MINMATCH;
if (depth==0) goto _storeSequence; if (depth==0) goto _storeSequence;
@@ -1623,19 +1578,16 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
matchLength = ml2, start = ip, offset=offsetFound; matchLength = ml2, start = ip, offset=offsetFound;
} }
if (matchLength < MINMATCH) if (matchLength < MINMATCH) {
{
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
continue; continue;
} }
/* let's try to find a better solution */ /* let's try to find a better solution */
if (depth>=1) if (depth>=1)
while (ip<ilimit) while (ip<ilimit) {
{
ip ++; ip ++;
if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
{
size_t mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH; size_t mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
int gain2 = (int)(mlRep * 3); int gain2 = (int)(mlRep * 3);
int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1); int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
@@ -1647,19 +1599,15 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
if ((ml2 >= MINMATCH) && (gain2 > gain1)) if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
{
matchLength = ml2, offset = offset2, start = ip; matchLength = ml2, offset = offset2, start = ip;
continue; /* search a better one */ continue; /* search a better one */
} } }
}
/* let's find an even better one */ /* let's find an even better one */
if ((depth==2) && (ip<ilimit)) if ((depth==2) && (ip<ilimit)) {
{
ip ++; ip ++;
if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
{
size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH; size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
int gain2 = (int)(ml2 * 4); int gain2 = (int)(ml2 * 4);
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
@@ -1671,19 +1619,15 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
if ((ml2 >= MINMATCH) && (gain2 > gain1)) if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
{
matchLength = ml2, offset = offset2, start = ip; matchLength = ml2, offset = offset2, start = ip;
continue; continue;
} } } }
}
}
break; /* nothing found : store previous solution */ break; /* nothing found : store previous solution */
} }
/* catch up */ /* catch up */
if (offset) if (offset) {
{
while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */ while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
{ start--; matchLength++; } { start--; matchLength++; }
offset_2 = offset_1; offset_1 = offset; offset_2 = offset_1; offset_1 = offset;
@@ -1699,8 +1643,7 @@ _storeSequence:
/* check immediate repcode */ /* check immediate repcode */
while ( (ip <= ilimit) while ( (ip <= ilimit)
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
{
/* store sequence */ /* store sequence */
matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
offset = offset_2; offset = offset_2;
@@ -1710,8 +1653,7 @@ _storeSequence:
ip += matchLength+MINMATCH; ip += matchLength+MINMATCH;
anchor = ip; anchor = ip;
continue; /* faster when present ... (?) */ continue; /* faster when present ... (?) */
} } }
}
/* Last Literals */ /* Last Literals */
{ {
@@ -1774,8 +1716,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
/* Match Loop */ /* Match Loop */
while (ip < ilimit) while (ip < ilimit) {
{
size_t matchLength=0; size_t matchLength=0;
size_t offset=0; size_t offset=0;
const BYTE* start=ip+1; const BYTE* start=ip+1;
@@ -1787,14 +1728,12 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip+1) == MEM_read32(repMatch)) if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
{
/* repcode detected we should take it */ /* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (depth==0) goto _storeSequence; if (depth==0) goto _storeSequence;
} } }
}
{ {
/* first search (depth 0) */ /* first search (depth 0) */
@@ -1804,27 +1743,23 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
matchLength = ml2, start = ip, offset=offsetFound; matchLength = ml2, start = ip, offset=offsetFound;
} }
if (matchLength < MINMATCH) if (matchLength < MINMATCH) {
{
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
continue; continue;
} }
/* let's try to find a better solution */ /* let's try to find a better solution */
if (depth>=1) if (depth>=1)
while (ip<ilimit) while (ip<ilimit) {
{
ip ++; ip ++;
current++; current++;
/* check repCode */ /* check repCode */
if (offset) if (offset) {
{
const U32 repIndex = (U32)(current - offset_1); const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip) == MEM_read32(repMatch)) if (MEM_read32(ip) == MEM_read32(repMatch)) {
{
/* repcode detected */ /* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
@@ -1832,8 +1767,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1); int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
if ((repLength >= MINMATCH) && (gain2 > gain1)) if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip; matchLength = repLength, offset = 0, start = ip;
} } }
}
/* search match, depth 1 */ /* search match, depth 1 */
{ {
@@ -1841,27 +1775,22 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
if ((ml2 >= MINMATCH) && (gain2 > gain1)) if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
{
matchLength = ml2, offset = offset2, start = ip; matchLength = ml2, offset = offset2, start = ip;
continue; /* search a better one */ continue; /* search a better one */
} } }
}
/* let's find an even better one */ /* let's find an even better one */
if ((depth==2) && (ip<ilimit)) if ((depth==2) && (ip<ilimit)) {
{
ip ++; ip ++;
current++; current++;
/* check repCode */ /* check repCode */
if (offset) if (offset) {
{
const U32 repIndex = (U32)(current - offset_1); const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip) == MEM_read32(repMatch)) if (MEM_read32(ip) == MEM_read32(repMatch)) {
{
/* repcode detected */ /* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
@@ -1869,8 +1798,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
if ((repLength >= MINMATCH) && (gain2 > gain1)) if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip; matchLength = repLength, offset = 0, start = ip;
} } }
}
/* search match, depth 2 */ /* search match, depth 2 */
{ {
@@ -1878,19 +1806,15 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
if ((ml2 >= MINMATCH) && (gain2 > gain1)) if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
{
matchLength = ml2, offset = offset2, start = ip; matchLength = ml2, offset = offset2, start = ip;
continue; continue;
} } } }
}
}
break; /* nothing found : store previous solution */ break; /* nothing found : store previous solution */
} }
/* catch up */ /* catch up */
if (offset) if (offset) {
{
U32 matchIndex = (U32)((start-base) - offset); U32 matchIndex = (U32)((start-base) - offset);
const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex; const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart; const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
@@ -1907,14 +1831,12 @@ _storeSequence:
} }
/* check immediate repcode */ /* check immediate repcode */
while (ip <= ilimit) while (ip <= ilimit) {
{
const U32 repIndex = (U32)((ip-base) - offset_2); const U32 repIndex = (U32)((ip-base) - offset_2);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip) == MEM_read32(repMatch)) if (MEM_read32(ip) == MEM_read32(repMatch)) {
{
/* repcode detected we should take it */ /* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
@@ -1925,8 +1847,7 @@ _storeSequence:
continue; /* faster when present ... (?) */ continue; /* faster when present ... (?) */
} }
break; break;
} } }
}
/* Last Literals */ /* Last Literals */
{ {
@@ -2161,12 +2082,43 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t dictSize) static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
{ {
/* note : magic number already checked */ /* note : magic number already checked */
size_t offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize, errorCode;
short offcodeNCount[MaxOff+1];
unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
const size_t hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize); const size_t hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted); if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
zc->flagHufTable = 1; zc->flagStaticTables = 1;
return hufHeaderSize; dict = (const char*)dict + hufHeaderSize;
dictSize -= hufHeaderSize;
offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildCTable(zc->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + offcodeHeaderSize;
dictSize -= offcodeHeaderSize;
matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildCTable(zc->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + matchlengthHeaderSize;
dictSize -= matchlengthHeaderSize;
litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildCTable(zc->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
return hufHeaderSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
} }
static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize) static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
{ {
if (dict && dictSize) if (dict && dictSize)
@@ -2240,8 +2192,7 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t maxDstSize)
size_t hbSize = 0; size_t hbSize = 0;
/* empty frame */ /* empty frame */
if (zc->stage==0) if (zc->stage==0) {
{
hbSize = zc->hbSize; hbSize = zc->hbSize;
if (maxDstSize <= hbSize) return ERROR(dstSize_tooSmall); if (maxDstSize <= hbSize) return ERROR(dstSize_tooSmall);
zc->stage = 1; zc->stage = 1;
+151 -67
View File
@@ -51,7 +51,7 @@
#endif #endif
/* ******************************************************* /*-*******************************************************
* Includes * Includes
*********************************************************/ *********************************************************/
#include <stdlib.h> /* calloc */ #include <stdlib.h> /* calloc */
@@ -67,7 +67,8 @@
# include "zstd_legacy.h" # include "zstd_legacy.h"
#endif #endif
/* *******************************************************
/*-*******************************************************
* Compiler specifics * Compiler specifics
*********************************************************/ *********************************************************/
#ifdef _MSC_VER /* Visual Studio */ #ifdef _MSC_VER /* Visual Studio */
@@ -85,7 +86,7 @@
#endif #endif
/* ************************************* /*-*************************************
* Local types * Local types
***************************************/ ***************************************/
typedef struct typedef struct
@@ -123,10 +124,10 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
struct ZSTD_DCtx_s struct ZSTD_DCtx_s
{ {
U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; FSE_DTable OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
U32 hufTableX4[HUF_DTABLE_SIZE(HufLog)]; unsigned hufTableX4[HUF_DTABLE_SIZE(HufLog)];
const void* previousDstEnd; const void* previousDstEnd;
const void* base; const void* base;
const void* vBase; const void* vBase;
@@ -134,9 +135,9 @@ struct ZSTD_DCtx_s
size_t expected; size_t expected;
size_t headerSize; size_t headerSize;
ZSTD_parameters params; ZSTD_parameters params;
blockType_t bType; blockType_t bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
ZSTD_dStage stage; ZSTD_dStage stage;
U32 flagHufTable; U32 flagStaticTables;
const BYTE* litPtr; const BYTE* litPtr;
size_t litBufSize; size_t litBufSize;
size_t litSize; size_t litSize;
@@ -144,6 +145,8 @@ struct ZSTD_DCtx_s
BYTE headerBuffer[ZSTD_frameHeaderSize_max]; BYTE headerBuffer[ZSTD_frameHeaderSize_max];
}; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */ }; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */
size_t sizeofDCtx (void) { return sizeof(ZSTD_DCtx); }
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
{ {
dctx->expected = ZSTD_frameHeaderSize_min; dctx->expected = ZSTD_frameHeaderSize_min;
@@ -153,7 +156,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
dctx->vBase = NULL; dctx->vBase = NULL;
dctx->dictEnd = NULL; dctx->dictEnd = NULL;
dctx->hufTableX4[0] = HufLog; dctx->hufTableX4[0] = HufLog;
dctx->flagHufTable = 0; dctx->flagStaticTables = 0;
return 0; return 0;
} }
@@ -197,27 +200,66 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
*/ */
/* Block format description /* Block format description
Literal Section - Sequences Section
Block = Literal Section - Sequences Section
Prerequisite : size of (compressed) block, maximum size of regenerated data
1) Literal Section 1) Literal Section
1.1) Header : up to 5 bytes
flags: 1.1) Header : 1-5 bytes
flags: 2 bits
00 compressed by Huff0 00 compressed by Huff0
01 is Raw (uncompressed) 01 unused
10 is Rle 10 is Raw (uncompressed)
11 unused 11 is Rle
Note : using 11 for Huff0 with precomputed table ? Note : using 01 => Huff0 with precomputed table ?
Note : delta map ? => compressed ? Note : delta map ? => compressed ?
Note 2 : 19 bits for sizes, seems a bit larger than necessary
Note 3 : RLE blocks ? 1.1.1) Huff0-compressed literal block : 3-5 bytes
srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
srcSize < 1 KB => 3 bytes (2-2-10-10)
srcSize < 16KB => 4 bytes (2-2-14-14)
else => 5 bytes (2-2-18-18)
big endian convention
1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
size : 5 bits: (IS_RAW<<6) + (0<<4) + size
12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
size&255
20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
size>>8&255
size&255
1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
size : 5 bits: (IS_RLE<<6) + (0<<4) + size
12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
size&255
20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
size>>8&255
size&255
1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
srcSize < 1 KB => 3 bytes (2-2-10-10)
srcSize < 16KB => 4 bytes (2-2-14-14)
else => 5 bytes (2-2-18-18)
big endian convention
1- CTable available (stored into workspace ?)
2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
1.2) Literal block content
1.2.1) Huff0 block, using sizes from header 1.2.1) Huff0 block, using sizes from header
See Huff0 format See Huff0 format
1.2.2) Huff0 block, using precomputed DTable 1.2.2) Huff0 block, using prepared table
_usingDTable variants
1.2.3) Raw content
1.2.4) single byte
1.2.3) uncompressed blocks
as the name says (both 2 or 3 bytes variants)
2) Sequences section 2) Sequences section
TO DO TO DO
@@ -331,7 +373,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4]; litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
break; break;
} }
if (litSize > BLOCKSIZE) return ERROR(corruption_detected);; if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
if (HUF_isError(singleStream ? if (HUF_isError(singleStream ?
HUF_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) : HUF_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :
@@ -350,7 +392,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
U32 lhSize = ((istart[0]) >> 4) & 3; U32 lhSize = ((istart[0]) >> 4) & 3;
if (lhSize != 1) /* only case supported for now : small litSize, single stream */ if (lhSize != 1) /* only case supported for now : small litSize, single stream */
return ERROR(corruption_detected); return ERROR(corruption_detected);
if (!dctx->flagHufTable) if (!dctx->flagStaticTables)
return ERROR(dictionary_corrupted); return ERROR(dictionary_corrupted);
/* 2 - 2 - 10 - 10 */ /* 2 - 2 - 10 - 10 */
@@ -448,14 +490,11 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLen
LLtype = *ip >> 6; LLtype = *ip >> 6;
Offtype = (*ip >> 4) & 3; Offtype = (*ip >> 4) & 3;
MLtype = (*ip >> 2) & 3; MLtype = (*ip >> 2) & 3;
if (*ip & 2) if (*ip & 2) {
{
dumpsLength = ip[2]; dumpsLength = ip[2];
dumpsLength += ip[1] << 8; dumpsLength += ip[1] << 8;
ip += 3; ip += 3;
} } else {
else
{
dumpsLength = ip[1]; dumpsLength = ip[1];
dumpsLength += (ip[0] & 1) << 8; dumpsLength += (ip[0] & 1) << 8;
ip += 2; ip += 2;
@@ -476,13 +515,18 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLen
switch(LLtype) switch(LLtype)
{ {
U32 max; U32 max;
case bt_rle : case FSE_ENCODING_RLE :
LLlog = 0; LLlog = 0;
FSE_buildDTable_rle(DTableLL, *ip++); break; FSE_buildDTable_rle(DTableLL, *ip++);
case bt_raw : break;
case FSE_ENCODING_RAW :
LLlog = LLbits; LLlog = LLbits;
FSE_buildDTable_raw(DTableLL, LLbits); break; FSE_buildDTable_raw(DTableLL, LLbits);
default : break;
case FSE_ENCODING_STATIC:
break;
case FSE_ENCODING_DYNAMIC :
default : /* impossible */
max = MaxLL; max = MaxLL;
headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip); headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
if (FSE_isError(headerSize)) return ERROR(GENERIC); if (FSE_isError(headerSize)) return ERROR(GENERIC);
@@ -494,15 +538,19 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLen
switch(Offtype) switch(Offtype)
{ {
U32 max; U32 max;
case bt_rle : case FSE_ENCODING_RLE :
Offlog = 0; Offlog = 0;
if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */ FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
break; break;
case bt_raw : case FSE_ENCODING_RAW :
Offlog = Offbits; Offlog = Offbits;
FSE_buildDTable_raw(DTableOffb, Offbits); break; FSE_buildDTable_raw(DTableOffb, Offbits);
default : break;
case FSE_ENCODING_STATIC:
break;
case FSE_ENCODING_DYNAMIC :
default : /* impossible */
max = MaxOff; max = MaxOff;
headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip); headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
if (FSE_isError(headerSize)) return ERROR(GENERIC); if (FSE_isError(headerSize)) return ERROR(GENERIC);
@@ -514,22 +562,26 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLen
switch(MLtype) switch(MLtype)
{ {
U32 max; U32 max;
case bt_rle : case FSE_ENCODING_RLE :
MLlog = 0; MLlog = 0;
if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
FSE_buildDTable_rle(DTableML, *ip++); break; FSE_buildDTable_rle(DTableML, *ip++);
case bt_raw : break;
case FSE_ENCODING_RAW :
MLlog = MLbits; MLlog = MLbits;
FSE_buildDTable_raw(DTableML, MLbits); break; FSE_buildDTable_raw(DTableML, MLbits);
default : break;
case FSE_ENCODING_STATIC:
break;
case FSE_ENCODING_DYNAMIC :
default : /* impossible */
max = MaxML; max = MaxML;
headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip); headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
if (FSE_isError(headerSize)) return ERROR(GENERIC); if (FSE_isError(headerSize)) return ERROR(GENERIC);
if (MLlog > MLFSELog) return ERROR(corruption_detected); if (MLlog > MLFSELog) return ERROR(corruption_detected);
ip += headerSize; ip += headerSize;
FSE_buildDTable(DTableML, norm, max, MLlog); FSE_buildDTable(DTableML, norm, max, MLlog);
} } }
}
return ip-istart; return ip-istart;
} }
@@ -564,12 +616,10 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
/* Literal length */ /* Literal length */
litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
prevOffset = litLength ? seq->offset : seqState->prevOffset; prevOffset = litLength ? seq->offset : seqState->prevOffset;
if (litLength == MaxLL) if (litLength == MaxLL) {
{
U32 add = *dumps++; U32 add = *dumps++;
if (add < 255) litLength += add; if (add < 255) litLength += add;
else else {
{
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
dumps += 3; dumps += 3;
} }
@@ -595,12 +645,10 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
/* MatchLength */ /* MatchLength */
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
if (matchLength == MaxML) if (matchLength == MaxML) {
{
U32 add = *dumps++; U32 add = *dumps++;
if (add < 255) matchLength += add; if (add < 255) matchLength += add;
else else {
{
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
dumps += 3; dumps += 3;
} }
@@ -613,6 +661,15 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
seq->offset = offset; seq->offset = offset;
seq->matchLength = matchLength; seq->matchLength = matchLength;
seqState->dumps = dumps; seqState->dumps = dumps;
#if 0
{
static U64 totalDecoded = 0;
printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
(U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
totalDecoded += litLength + matchLength;
}
#endif
} }
@@ -657,8 +714,7 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
op = oLitEnd + length1; op = oLitEnd + length1;
sequence.matchLength -= length1; sequence.matchLength -= length1;
match = base; match = base;
} } }
}
/* match within prefix */ /* match within prefix */
if (sequence.offset < 8) { if (sequence.offset < 8) {
@@ -671,8 +727,7 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
match += dec32table[sequence.offset]; match += dec32table[sequence.offset];
ZSTD_copy4(op+4, match); ZSTD_copy4(op+4, match);
match -= sub2; match -= sub2;
} } else {
else {
ZSTD_copy8(op, match); ZSTD_copy8(op, match);
} }
op += 8; match += 8; op += 8; match += 8;
@@ -683,9 +738,9 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
match += oend_8 - op; match += oend_8 - op;
op = oend_8; op = oend_8;
} }
while (op < oMatchEnd) *op++ = *match++; while (op < oMatchEnd)
} *op++ = *match++;
else { } else {
ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */ ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
} }
return sequenceLength; return sequenceLength;
@@ -718,7 +773,7 @@ static size_t ZSTD_decompressSequences(
/* Build Decoding Tables */ /* Build Decoding Tables */
errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
DTableLL, DTableML, DTableOffb, DTableLL, DTableML, DTableOffb,
ip, iend-ip); ip, seqSize);
if (ZSTD_isError(errorCode)) return errorCode; if (ZSTD_isError(errorCode)) return errorCode;
ip += errorCode; ip += errorCode;
@@ -757,8 +812,7 @@ static size_t ZSTD_decompressSequences(
if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
if (op != litPtr) memcpy(op, litPtr, lastLLSize); if (op != litPtr) memcpy(op, litPtr, lastLLSize);
op += lastLLSize; op += lastLLSize;
} } }
}
return op-ostart; return op-ostart;
} }
@@ -1018,10 +1072,40 @@ static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{ {
size_t hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize); size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
short offcodeNCount[MaxOff+1];
U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted); if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
dctx->flagHufTable = 1; dict = (const char*)dict + hSize;
return hSize; dictSize -= hSize;
offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + offcodeHeaderSize;
dictSize -= offcodeHeaderSize;
matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + matchlengthHeaderSize;
dictSize -= matchlengthHeaderSize;
litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
dctx->flagStaticTables = 1;
return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
} }
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+8 -2
View File
@@ -94,6 +94,12 @@ static const size_t ZSTD_frameHeaderSize_min = 5;
#define OffFSELog 9 #define OffFSELog 9
#define MaxSeq MAX(MaxLL, MaxML) #define MaxSeq MAX(MaxLL, MaxML)
#define FSE_ENCODING_RAW 0
#define FSE_ENCODING_RLE 1
#define FSE_ENCODING_STATIC 2
#define FSE_ENCODING_DYNAMIC 3
#define HufLog 12 #define HufLog 12
#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
@@ -104,9 +110,9 @@ static const size_t ZSTD_frameHeaderSize_min = 5;
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
/* ****************************************** /*-*******************************************
* Shared functions to include for inlining * Shared functions to include for inlining
********************************************/ *********************************************/
static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
+14 -7
View File
@@ -293,11 +293,10 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
milliTime = BMK_GetMilliStart(); milliTime = BMK_GetMilliStart();
while (BMK_GetMilliStart() == milliTime); while (BMK_GetMilliStart() == milliTime);
milliTime = BMK_GetMilliStart(); milliTime = BMK_GetMilliStart();
while (BMK_GetMilliSpan(milliTime) < TIMELOOP) while (BMK_GetMilliSpan(milliTime) < TIMELOOP) {
{
ZSTD_compressBegin_advanced(refCtx, dictBuffer, dictBufferSize, ZSTD_getParams(cLevel, dictBufferSize+largestBlockSize)); ZSTD_compressBegin_advanced(refCtx, dictBuffer, dictBufferSize, ZSTD_getParams(cLevel, dictBufferSize+largestBlockSize));
for (blockNb=0; blockNb<nbBlocks; blockNb++) //ZSTD_compressBegin_advanced(refCtx, dictBuffer, dictBufferSize, ZSTD_getParams(cLevel, 0));
{ for (blockNb=0; blockNb<nbBlocks; blockNb++) {
ZSTD_copyCCtx(ctx, refCtx); ZSTD_copyCCtx(ctx, refCtx);
size_t rSize = ZSTD_compressContinue(ctx, size_t rSize = ZSTD_compressContinue(ctx,
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
@@ -309,6 +308,10 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
blockTable[blockNb].cRoom - rSize); blockTable[blockNb].cRoom - rSize);
if (ZSTD_isError(rSize)) EXM_THROW(2, "ZSTD_compressEnd() failed : %s", ZSTD_getErrorName(rSize)); if (ZSTD_isError(rSize)) EXM_THROW(2, "ZSTD_compressEnd() failed : %s", ZSTD_getErrorName(rSize));
blockTable[blockNb].cSize += rSize; blockTable[blockNb].cSize += rSize;
if (blockNb==999999999)
printf("%4u : %6u => %6u bytes (%08X) \n",
blockNb, (U32)blockTable[blockNb].srcSize, (U32)blockTable[blockNb].cSize, XXH32(blockTable[blockNb].cPtr, blockTable[blockNb].cSize, 0));
} }
nbLoops++; nbLoops++;
} }
@@ -340,7 +343,8 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
blockTable[blockNb].cPtr, blockTable[blockNb].cSize); blockTable[blockNb].cPtr, blockTable[blockNb].cSize);
if (ZSTD_isError(regenSize)) if (ZSTD_isError(regenSize))
EXM_THROW(3, "ZSTD_decompress_usingDict() failed : %s", ZSTD_getErrorName(regenSize)); EXM_THROW(3, "ZSTD_decompress_usingPreparedDCtx() failed on block %u : %s",
blockNb, ZSTD_getErrorName(regenSize));
blockTable[blockNb].resSize = regenSize; blockTable[blockNb].resSize = regenSize;
} } } }
@@ -364,8 +368,11 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
} }
pos = (U32)(u - bacc); pos = (U32)(u - bacc);
bNb = pos / (128 KB); bNb = pos / (128 KB);
printf("(segment %u, block %u, pos %u) \n", segNb, bNb, pos); printf("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
break; break;
}
if (u==srcSize-1) { /* should never happen */
printf("no difference detected\n");
} } } }
break; break;
} }
@@ -375,7 +382,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
if (crcOrig == crcCheck) if (crcOrig == crcCheck)
DISPLAY("%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s ,%6.1f MB/s \n", cLevel, displayName, (int)srcSize, (int)cSize, ratio, (double)srcSize / fastestC / 1000., (double)srcSize / fastestD / 1000.); DISPLAY("%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s ,%6.1f MB/s \n", cLevel, displayName, (int)srcSize, (int)cSize, ratio, (double)srcSize / fastestC / 1000., (double)srcSize / fastestD / 1000.);
else else
DISPLAY("\n"); DISPLAY("%2i-\n", cLevel);
} }
/* clean up */ /* clean up */