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
+209 -258
View File
@@ -126,7 +126,10 @@ struct ZSTD_CCtx_s
U32* hashTable;
U32* contentTable;
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;
/* 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;
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 size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32);
const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize);
if (zc->workSpaceSize < neededSpace)
{
if (zc->workSpaceSize < neededSpace) {
free(zc->workSpace);
zc->workSpace = malloc(neededSpace);
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->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog);
zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
zc->flagHufTable = 0;
zc->flagStaticTables = 0;
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->lowLimit = srcCCtx->lowLimit;
dstCCtx->flagHufTable = srcCCtx->flagHufTable;
if (dstCCtx->flagHufTable)
/* copy entropy tables */
dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
if (dstCCtx->flagStaticTables) {
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;
}
@@ -271,8 +277,7 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
U32* table32 = zc->hashTable;
U32 index;
for (index=0 ; index < tableSpaceU32 ; index++)
{
for (index=0 ; index < tableSpaceU32 ; index++) {
if (table32[index] < reducerValue) table32[index] = 0;
else table32[index] -= reducerValue;
}
@@ -338,15 +343,35 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
1.2.1) Huff0 block, using sizes from header
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
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)
@@ -399,7 +424,7 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t maxDstSize, const
BYTE* const ostart = (BYTE* const)dst;
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)
{
@@ -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 (zc->flagHufTable && (lhSize==3))
{
if (zc->flagStaticTables && (lhSize==3)) {
hType = IS_PCH;
singleStream = 1;
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)
: 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];
S16 norm[MaxSeq+1];
size_t mostFrequent;
U32 max = 255;
U32 tableLog = 11;
U32 CTable_LitLength [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL )];
U32 CTable_OffsetBits [FSE_CTABLE_SIZE_U32(OffFSELog,MaxOff)];
U32 CTable_MatchLength[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML )];
U32 max;
FSE_CTable* CTable_LitLength = zc->litlengthCTable;
FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
const BYTE* const op_lit_start = seqStorePtr->litStart;
const BYTE* const llTable = seqStorePtr->litLengthStart;
@@ -516,7 +537,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
{
size_t cSize;
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)
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 */
{
size_t dumpsLength = seqStorePtr->dumps - seqStorePtr->dumpsStart;
if (dumpsLength < 512)
{
if (dumpsLength < 512) {
op[0] = (BYTE)(dumpsLength >> 8);
op[1] = (BYTE)(dumpsLength);
op += 2;
}
else
{
} else {
op[0] = 2;
op[1] = (BYTE)(dumpsLength>>8);
op[2] = (BYTE)(dumpsLength);
@@ -553,94 +571,86 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
op += dumpsLength;
}
#define MIN_SEQ_FOR_DYNAMIC_FSE 64
#define MAX_SEQ_FOR_STATIC_FSE 1000
/* CTable for Literal Lengths */
max = MaxLL;
mostFrequent = FSE_countFast(count, &max, seqStorePtr->litLengthStart, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2))
{
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
*op++ = *(seqStorePtr->litLengthStart);
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
LLtype = bt_rle;
}
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (LLbits-1))))
{
LLtype = FSE_ENCODING_RLE;
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
LLtype = FSE_ENCODING_STATIC;
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LLbits-1)))) {
FSE_buildCTable_raw(CTable_LitLength, LLbits);
LLtype = bt_raw;
}
else
{
LLtype = FSE_ENCODING_RAW;
} else {
size_t NCountSize;
tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize;
FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
LLtype = bt_compressed;
LLtype = FSE_ENCODING_DYNAMIC;
}
/* CTable for Offsets codes */
{
/* create Offset codes */
size_t i;
max = MaxOff;
for (i=0; i<nbSeq; i++)
{
/* CTable for Offset codes */
{ /* create Offset codes */
size_t i; for (i=0; i<nbSeq; i++) {
offCodeTable[i] = (BYTE)ZSTD_highbit(offsetTable[i]) + 1;
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;
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
Offtype = bt_rle;
}
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (Offbits-1))))
{
Offtype = FSE_ENCODING_RLE;
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
Offtype = FSE_ENCODING_STATIC;
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
Offtype = bt_raw;
}
else
{
Offtype = FSE_ENCODING_RAW;
} else {
size_t NCountSize;
tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize;
FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
Offtype = bt_compressed;
Offtype = FSE_ENCODING_DYNAMIC;
}
/* CTable for MatchLengths */
max = MaxML;
mostFrequent = FSE_countFast(count, &max, seqStorePtr->matchLengthStart, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2))
{
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
*op++ = *seqStorePtr->matchLengthStart;
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
MLtype = bt_rle;
}
else if ((nbSeq < 64) || (mostFrequent < (nbSeq >> (MLbits-1))))
{
MLtype = FSE_ENCODING_RLE;
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
MLtype = FSE_ENCODING_STATIC;
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (MLbits-1)))) {
FSE_buildCTable_raw(CTable_MatchLength, MLbits);
MLtype = bt_raw;
}
else
{
MLtype = FSE_ENCODING_RAW;
} else {
size_t NCountSize;
tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
op += NCountSize;
FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
MLtype = bt_compressed;
MLtype = FSE_ENCODING_DYNAMIC;
}
seqHead[0] += (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
zc->flagStaticTables = 0;
/* Encoding Sequences */
{
@@ -657,14 +667,13 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
FSE_initCState(&stateOffsetBits, CTable_OffsetBits);
FSE_initCState(&stateLitLength, CTable_LitLength);
for (i=(int)nbSeq-1; i>=0; i--)
{
BYTE matchLength = mlTable[i];
for (i=(int)nbSeq-1; i>=0; i--) {
BYTE mlCode = mlTable[i];
U32 offset = offsetTable[i];
BYTE offCode = offCodeTable[i]; /* 32b*/ /* 64b*/
U32 nbBits = (offCode-1) * (!!offCode);
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 */
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */
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
static const BYTE* g_start = NULL;
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",
(U32)(literals - g_start), (U32)litLength, (U32)matchCode+4, (U32)offsetCode);
#endif
@@ -709,34 +718,28 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
seqStorePtr->lit += litLength;
/* literal Length */
if (litLength >= MaxLL)
{
if (litLength >= MaxLL) {
*(seqStorePtr->litLength++) = MaxLL;
if (litLength<255 + MaxLL)
if (litLength<255 + MaxLL) {
*(seqStorePtr->dumps++) = (BYTE)(litLength - MaxLL);
else
{
} else {
*(seqStorePtr->dumps++) = 255;
MEM_writeLE32(seqStorePtr->dumps, (U32)litLength); seqStorePtr->dumps += 3;
}
}
} }
else *(seqStorePtr->litLength++) = (BYTE)litLength;
/* match offset */
*(seqStorePtr->offset++) = (U32)offsetCode;
/* match Length */
if (matchCode >= MaxML)
{
if (matchCode >= MaxML) {
*(seqStorePtr->matchLength++) = MaxML;
if (matchCode < 255+MaxML)
if (matchCode < 255+MaxML) {
*(seqStorePtr->dumps++) = (BYTE)(matchCode - MaxML);
else
{
} else {
*(seqStorePtr->dumps++) = 255;
MEM_writeLE32(seqStorePtr->dumps, (U32)matchCode); seqStorePtr->dumps += 3;
}
}
} }
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;
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);
if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
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* const iend = (const BYTE*) end;
while(ip <= iend)
{
while(ip <= iend) {
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
ip += FILLHASHSTEP;
}
@@ -947,8 +948,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
/* init */
ZSTD_resetSeqStore(seqStorePtr);
if (ip < lowest+4)
{
if (ip < lowest+4) {
hashTable[ZSTD_hashPtr(lowest+1, hBits, mls)] = lowIndex+1;
hashTable[ZSTD_hashPtr(lowest+2, hBits, mls)] = lowIndex+2;
hashTable[ZSTD_hashPtr(lowest+3, hBits, mls)] = lowIndex+3;
@@ -956,8 +956,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
}
/* 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 offset;
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);
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);
ip++;
offset = 0;
}
else
{
} else {
if ( (matchIndex <= lowIndex) ||
(MEM_read32(match) != MEM_read32(ip)) )
{
(MEM_read32(match) != MEM_read32(ip)) ) {
ip += ((ip-anchor) >> g_searchStrength) + 1;
continue;
}
@@ -992,15 +987,13 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
ip += mlCode + MINMATCH;
anchor = ip;
if (ip <= ilimit)
{
if (ip <= ilimit) {
/* Fill Table */
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);
/* check immediate repcode */
while ( (ip <= ilimit)
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )
{
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
/* store sequence */
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 */
@@ -1009,9 +1002,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
ip += rlCode+MINMATCH;
anchor = ip;
continue; /* faster when present ... (?) */
}
}
}
} } }
/* Last Literals */
{
@@ -1067,18 +1058,15 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
/* init */
ZSTD_resetSeqStore(seqStorePtr);
{
/* 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+1, hBits, mls)] = (U32)(ip-base+1);
hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip-base+2);
hashTable[ZSTD_hashPtr(ip+3, hBits, mls)] = (U32)(ip-base+3);
ip += 4;
}
/* 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+1, hBits, mls)] = (U32)(ip-base+1);
hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip-base+2);
hashTable[ZSTD_hashPtr(ip+3, hBits, mls)] = (U32)(ip-base+3);
ip += 4;
/* 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 U32 matchIndex = hashTable[h];
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 */
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;
mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
ip++;
offset = 0;
}
else
{
} else {
if ( (matchIndex < lowLimit) ||
(MEM_read32(match) != MEM_read32(ip)) )
{ ip += ((ip-anchor) >> g_searchStrength) + 1; continue; }
@@ -1108,32 +1093,28 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
mlCode = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iend, matchEnd, lowPrefixPtr);
while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
offset = current - matchIndex;
offset_2 = offset_1;
offset_1 = offset;
}
}
} }
/* found a match : store it */
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
ip += mlCode + MINMATCH;
anchor = ip;
if (ip <= ilimit)
{
if (ip <= ilimit) {
/* Fill Table */
hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
while (ip <= ilimit)
{
while (ip <= ilimit) {
U32 current2 = (U32)(ip-base);
const U32 repIndex2 = current2 - offset_2;
const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
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;
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 */
@@ -1144,9 +1125,7 @@ void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
continue;
}
break;
}
}
}
} } }
/* 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 */
while (nbCompares-- && (matchIndex > windowLow))
{
while (nbCompares-- && (matchIndex > windowLow)) {
U32* nextPtr = bt + 2*(matchIndex & btMask);
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 */
if (matchIndex == predictedSmall)
{ /* no need to check length, result known */
if (matchIndex == predictedSmall) {
/* no need to check length, result known */
*smallerPtr = matchIndex;
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
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;
}
if (matchIndex == predictedLarge)
{
if (matchIndex == predictedLarge) {
*largerPtr = matchIndex;
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
largerPtr = nextPtr;
@@ -1239,14 +1216,11 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
continue;
}
if ((!extDict) || (matchIndex+matchLength >= dictLimit))
{
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
match = base + matchIndex;
if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
}
else
{
} else {
match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
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 */
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 */
*smallerPtr = matchIndex; /* update smaller idx */
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 */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
}
else
{
} else {
/* match is larger than current */
*largerPtr = matchIndex;
commonLengthLarger = matchLength;
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
largerPtr = nextPtr;
matchIndex = nextPtr[0];
}
}
} }
*smallerPtr = *largerPtr = 0;
return (matchEndIdx > current + 8) ? matchEndIdx - current - 8 : 1;
@@ -1326,28 +1296,23 @@ size_t ZSTD_insertBtAndFindBestMatch (
hashTable[h] = current; /* Update Hash Table */
while (nbCompares-- && (matchIndex > windowLow))
{
while (nbCompares-- && (matchIndex > windowLow)) {
U32* nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match;
if ((!extDict) || (matchIndex+matchLength >= dictLimit))
{
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
match = base + matchIndex;
if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
}
else
{
} else {
match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
if (matchIndex+matchLength >= dictLimit)
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
}
if (matchLength > bestLength)
{
if (matchLength > bestLength) {
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
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) */
}
if (match[matchLength] < ip[matchLength])
{
if (match[matchLength] < ip[matchLength]) {
/* match is smaller than current */
*smallerPtr = matchIndex; /* update smaller idx */
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 */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
}
else
{
} else {
/* match is larger than current */
*largerPtr = matchIndex;
commonLengthLarger = matchLength;
@@ -1472,8 +1434,7 @@ static U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
const U32 target = (U32)(ip - base);
U32 idx = zc->nextToUpdate;
while(idx < target)
{
while(idx < target) {
size_t h = ZSTD_hashPtr(base+idx, hashLog, mls);
NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
hashTable[h] = idx;
@@ -1511,18 +1472,14 @@ size_t ZSTD_HcFindBestMatch_generic (
/* HC4 match finder */
matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
while ((matchIndex>lowLimit) && (nbAttempts))
{
while ((matchIndex>lowLimit) && (nbAttempts)) {
size_t currentMl=0;
nbAttempts--;
if ((!extDict) || matchIndex >= dictLimit)
{
if ((!extDict) || matchIndex >= dictLimit) {
match = base + matchIndex;
if (match[ml] == ip[ml]) /* potentially better */
currentMl = ZSTD_count(ip, match, iLimit);
}
else
{
} else {
match = dictBase + matchIndex;
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;
@@ -1601,15 +1558,13 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
/* Match Loop */
while (ip < ilimit)
{
while (ip < ilimit) {
size_t matchLength=0;
size_t offset=0;
const BYTE* start=ip+1;
/* 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 */
matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend) + MINMATCH;
if (depth==0) goto _storeSequence;
@@ -1623,19 +1578,16 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
matchLength = ml2, start = ip, offset=offsetFound;
}
if (matchLength < MINMATCH)
{
if (matchLength < MINMATCH) {
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
continue;
}
/* let's try to find a better solution */
if (depth>=1)
while (ip<ilimit)
{
while (ip<ilimit) {
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;
int gain2 = (int)(mlRep * 3);
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);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
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;
continue; /* search a better one */
}
}
} }
/* let's find an even better one */
if ((depth==2) && (ip<ilimit))
{
if ((depth==2) && (ip<ilimit)) {
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;
int gain2 = (int)(ml2 * 4);
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);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
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;
continue;
}
}
}
} } }
break; /* nothing found : store previous solution */
}
/* catch up */
if (offset)
{
if (offset) {
while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
{ start--; matchLength++; }
offset_2 = offset_1; offset_1 = offset;
@@ -1699,8 +1643,7 @@ _storeSequence:
/* check immediate repcode */
while ( (ip <= ilimit)
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )
{
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
/* store sequence */
matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
offset = offset_2;
@@ -1710,8 +1653,7 @@ _storeSequence:
ip += matchLength+MINMATCH;
anchor = ip;
continue; /* faster when present ... (?) */
}
}
} }
/* Last Literals */
{
@@ -1774,8 +1716,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
/* Match Loop */
while (ip < ilimit)
{
while (ip < ilimit) {
size_t matchLength=0;
size_t offset=0;
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 repMatch = repBase + repIndex;
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 */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (depth==0) goto _storeSequence;
}
}
} }
{
/* first search (depth 0) */
@@ -1804,27 +1743,23 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
matchLength = ml2, start = ip, offset=offsetFound;
}
if (matchLength < MINMATCH)
{
if (matchLength < MINMATCH) {
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
continue;
}
/* let's try to find a better solution */
if (depth>=1)
while (ip<ilimit)
{
while (ip<ilimit) {
ip ++;
current++;
/* check repCode */
if (offset)
{
if (offset) {
const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip) == MEM_read32(repMatch))
{
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
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);
if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip;
}
}
} }
/* 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);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
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;
continue; /* search a better one */
}
}
} }
/* let's find an even better one */
if ((depth==2) && (ip<ilimit))
{
if ((depth==2) && (ip<ilimit)) {
ip ++;
current++;
/* check repCode */
if (offset)
{
if (offset) {
const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
if (MEM_read32(ip) == MEM_read32(repMatch))
{
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
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);
if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip;
}
}
} }
/* 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);
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
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;
continue;
}
}
}
} } }
break; /* nothing found : store previous solution */
}
/* catch up */
if (offset)
{
if (offset) {
U32 matchIndex = (U32)((start-base) - offset);
const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
@@ -1907,14 +1831,12 @@ _storeSequence:
}
/* check immediate repcode */
while (ip <= ilimit)
{
while (ip <= ilimit) {
const U32 repIndex = (U32)((ip-base) - offset_2);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
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 */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
@@ -1925,8 +1847,7 @@ _storeSequence:
continue; /* faster when present ... (?) */
}
break;
}
}
} }
/* 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)
{
/* 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);
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
zc->flagHufTable = 1;
return hufHeaderSize;
zc->flagStaticTables = 1;
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)
{
if (dict && dictSize)
@@ -2240,8 +2192,7 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t maxDstSize)
size_t hbSize = 0;
/* empty frame */
if (zc->stage==0)
{
if (zc->stage==0) {
hbSize = zc->hbSize;
if (maxDstSize <= hbSize) return ERROR(dstSize_tooSmall);
zc->stage = 1;