rollbuffer refactor

This commit is contained in:
Yann Collet
2015-11-23 13:34:21 +01:00
parent d7233d6e14
commit 5054ee0cc0
3 changed files with 101 additions and 120 deletions
+1
View File
@@ -68,6 +68,7 @@ extern "C" {
#define ERROR_LIST(ITEM) \ #define ERROR_LIST(ITEM) \
ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \ ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \
ITEM(PREFIX(mode_unsupported)) \
ITEM(PREFIX(memory_allocation)) \ ITEM(PREFIX(memory_allocation)) \
ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \ ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \
ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \ ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \
+1 -1
View File
@@ -475,7 +475,7 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
MEM_STATIC unsigned BIT_highbit32 (register U32 val) MEM_STATIC unsigned BIT_highbit32 (register U32 val)
{ {
# if defined(_MSC_VER) /* Visual */ # if defined(_MSC_VER) /* Visual */
unsigned long r; unsigned long r=0;
_BitScanReverse ( &r, val ); _BitScanReverse ( &r, val );
return (unsigned) r; return (unsigned) r;
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
+97 -117
View File
@@ -303,7 +303,7 @@ static size_t ZSTD_compressLiterals (void* dst, size_t maxDstSize,
#define LITERAL_NOENTROPY 63 /* cheap heuristic */ #define LITERAL_NOENTROPY 63 /* cheap heuristic */
size_t ZSTD_compressSequences(BYTE* dst, size_t maxDstSize, size_t ZSTD_compressSequences(void* dst, size_t maxDstSize,
const seqStore_t* seqStorePtr, const seqStore_t* seqStorePtr,
size_t srcSize) size_t srcSize)
{ {
@@ -322,8 +322,9 @@ size_t ZSTD_compressSequences(BYTE* dst, size_t maxDstSize,
const BYTE* const mlTable = seqStorePtr->matchLengthStart; const BYTE* const mlTable = seqStorePtr->matchLengthStart;
const U32* const offsetTable = seqStorePtr->offsetStart; const U32* const offsetTable = seqStorePtr->offsetStart;
BYTE* const offCodeTable = seqStorePtr->offCodeStart; BYTE* const offCodeTable = seqStorePtr->offCodeStart;
BYTE* op = dst; BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = dst + maxDstSize; BYTE* op = ostart;
BYTE* const oend = ostart + maxDstSize;
const size_t nbSeq = llPtr - llTable; const size_t nbSeq = llPtr - llTable;
const size_t minGain = ZSTD_minGain(srcSize); const size_t minGain = ZSTD_minGain(srcSize);
const size_t maxCSize = srcSize - minGain; const size_t maxCSize = srcSize - minGain;
@@ -500,9 +501,9 @@ size_t ZSTD_compressSequences(BYTE* dst, size_t maxDstSize,
} }
/* check compressibility */ /* check compressibility */
if ((size_t)(op-dst) >= maxCSize) return 0; if ((size_t)(op-ostart) >= maxCSize) return 0;
return op - dst; return op - ostart;
} }
@@ -585,7 +586,7 @@ static unsigned ZSTD_highbit(U32 val)
# endif # endif
} }
MEM_STATIC unsigned ZSTD_NbCommonBytes (register size_t val) static unsigned ZSTD_NbCommonBytes (register size_t val)
{ {
if (MEM_isLittleEndian()) if (MEM_isLittleEndian())
{ {
@@ -654,7 +655,7 @@ MEM_STATIC unsigned ZSTD_NbCommonBytes (register size_t val)
} }
MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
{ {
const BYTE* const pStart = pIn; const BYTE* const pStart = pIn;
@@ -672,6 +673,21 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pI
return (size_t)(pIn - pStart); return (size_t)(pIn - pStart);
} }
/** ZSTD_count_2segments
* can count match length with ip & match in potentially 2 different segments.
* convention : on reaching mEnd, match count continue starting from iStart
*/
static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
{
size_t matchLength;
const BYTE* vEnd = ip + (mEnd - match);
if (vEnd > iEnd) vEnd = iEnd;
matchLength = ZSTD_count(ip, match, vEnd);
if (match + matchLength == mEnd)
matchLength += ZSTD_count(ip+matchLength, iStart, iEnd);
return matchLength;
}
/* ************************************* /* *************************************
@@ -723,7 +739,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx,
const BYTE* const istart = (const BYTE*)src; const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart; const BYTE* ip = istart;
const BYTE* anchor = istart; const BYTE* anchor = istart;
const BYTE* const lowest = base + ctx->lowLimit; const BYTE* const lowest = base + ctx->dictLimit;
const BYTE* const iend = istart + srcSize; const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8; const BYTE* const ilimit = iend - 8;
@@ -743,7 +759,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx,
/* 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 matchLength; 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);
const BYTE* match = base + hashTable[h]; const BYTE* match = base + hashTable[h];
@@ -751,7 +767,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx,
if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))
{ {
matchLength = 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;
} }
@@ -763,22 +779,22 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx,
ip += ((ip-anchor) >> g_searchStrength) + 1; ip += ((ip-anchor) >> g_searchStrength) + 1;
continue; continue;
} }
matchLength = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend); mlCode = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend);
while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; matchLength++; } /* catch up */
offset = ip-match; offset = ip-match;
while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
offset_2 = offset_1; offset_2 = offset_1;
offset_1 = offset; offset_1 = offset;
} }
/* match found */ /* match found */
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, matchLength); ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
ip += matchLength + MINMATCH; hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip+2-base); /* can't use current : ip may have changed */
ip += mlCode + MINMATCH;
anchor = ip; anchor = ip;
if (ip <= ilimit) if (ip <= ilimit)
{ {
/* Fill Table */ /* Fill Table */
hashTable[ZSTD_hashPtr(ip-2-matchLength, hBits, mls)] = (U32)(ip-2-matchLength-base);
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)
@@ -804,7 +820,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx,
} }
/* Finale compression stage */ /* Finale compression stage */
return ZSTD_compressSequences((BYTE*)dst, maxDstSize, return ZSTD_compressSequences(dst, maxDstSize,
seqStorePtr, srcSize); seqStorePtr, srcSize);
} }
@@ -844,6 +860,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* ip = istart; const BYTE* ip = istart;
const BYTE* anchor = istart; const BYTE* anchor = istart;
const U32 lowLimit = ctx->lowLimit; const U32 lowLimit = ctx->lowLimit;
const BYTE* const dictStart = dictBase + lowLimit;
const U32 dictLimit = ctx->dictLimit; const U32 dictLimit = ctx->dictLimit;
const BYTE* const lowPrefixPtr = base + dictLimit; const BYTE* const lowPrefixPtr = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit;
@@ -871,12 +888,11 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
const U32 matchIndex = hashTable[h]; const U32 matchIndex = hashTable[h];
const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base; const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
const BYTE* match = matchBase + matchIndex; const BYTE* match = matchBase + matchIndex;
const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictBase + lowLimit : lowPrefixPtr;
const U32 current = (U32)(ip-base); const U32 current = (U32)(ip-base);
const U32 repIndex = current + 1 - offset_1; const U32 repIndex = current + 1 - offset_1;
const BYTE* repBase = repIndex < dictLimit ? dictBase : base; const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* repMatch = repBase + repIndex; const BYTE* repMatch = repBase + repIndex;
size_t matchLength; size_t mlCode;
U32 offset; U32 offset;
hashTable[h] = current; /* update hash table */ hashTable[h] = current; /* update hash table */
@@ -884,11 +900,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
&& (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;
const BYTE* vEnd = ip+1 + (repMatchEnd-repMatch); mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
if (vEnd > iend) vEnd = iend;
matchLength = ZSTD_count(ip+1+MINMATCH, repMatch+MINMATCH, vEnd);
if (repMatch + matchLength + MINMATCH == dictEnd)
matchLength += ZSTD_count(ip+1 + matchLength + MINMATCH, lowPrefixPtr, iend);
ip++; ip++;
offset = 0; offset = 0;
} }
@@ -899,26 +911,24 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
{ ip += ((ip-anchor) >> g_searchStrength) + 1; continue; } { ip += ((ip-anchor) >> g_searchStrength) + 1; continue; }
{ {
const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend; const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
const BYTE* iEndCount = (matchEnd - match < iend - ip) ? ip + (matchEnd - match) : iend; const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
matchLength = ZSTD_count(ip+MINMATCH, match+MINMATCH, iEndCount); mlCode = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iend, matchEnd, lowPrefixPtr);
if (match + matchLength + MINMATCH == dictEnd) while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
matchLength += ZSTD_count(ip + matchLength + MINMATCH, lowPrefixPtr, iend);
while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; matchLength++; } /* catch up */
offset = current - matchIndex; offset = current - matchIndex;
offset_2 = offset_1; offset_2 = offset_1;
offset_1 = offset; offset_1 = offset;
} }
} }
/* found a match */ /* found a match : store it */
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, matchLength); ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
ip += matchLength + MINMATCH; hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip+2-base); /* can't use current : ip may have changed */
ip += mlCode + MINMATCH;
anchor = ip; anchor = ip;
if (ip <= ilimit) if (ip <= ilimit)
{ {
/* Fill Table */ /* Fill Table */
hashTable[ZSTD_hashPtr(ip-2-matchLength, hBits, mls)] = (U32)(ip-2-matchLength-base);
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)
@@ -929,16 +939,12 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit)) if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) && (MEM_read32(repMatch2) == MEM_read32(ip)) )
{ {
size_t maxIlength = iend - ip; const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
size_t maxMlength = repIndex2 < dictLimit ? (size_t)(dictLimit - repIndex2) : (size_t)(iend - repMatch2); size_t repLength2 = ZSTD_count_2segments(ip+MINMATCH, repMatch2+MINMATCH, iend, repEnd2, lowPrefixPtr);
size_t maxML = MIN(maxMlength, maxIlength); U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
size_t ml = ZSTD_count(ip+MINMATCH, repMatch2+MINMATCH, ip + maxML); ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2);
U32 tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
if (ml+MINMATCH == maxMlength) /* reached end of extDict */ ip += repLength2+MINMATCH;
ml += ZSTD_count(ip+MINMATCH+ml, lowPrefixPtr, iend);
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, ml);
ip += ml+MINMATCH;
anchor = ip; anchor = ip;
continue; continue;
} }
@@ -955,7 +961,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
} }
/* Finale compression stage */ /* Finale compression stage */
return ZSTD_compressSequences((BYTE*)dst, maxDstSize, return ZSTD_compressSequences(dst, maxDstSize,
seqStorePtr, srcSize); seqStorePtr, srcSize);
} }
@@ -1020,7 +1026,8 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
match = base + matchIndex; match = base + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
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; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */
@@ -1083,14 +1090,15 @@ size_t ZSTD_insertBtAndFindBestMatch (
const BYTE* match = base + matchIndex; const BYTE* match = base + matchIndex;
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); if (match[matchLength] == ip[matchLength])
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
if (matchLength > bestLength) if (matchLength > bestLength)
{ {
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)) )
bestLength = matchLength, *offsetPtr = current - matchIndex; bestLength = matchLength, *offsetPtr = current - matchIndex;
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; /* just 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])
@@ -1098,18 +1106,18 @@ size_t ZSTD_insertBtAndFindBestMatch (
/* 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 */
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
if (matchIndex <= btLow) smallerPtr=&dummy32; /* beyond tree size, stop the search */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
matchIndex = (matchIndex <= btLow) ? windowLow : nextPtr[1];
} }
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 */
largerPtr = nextPtr; largerPtr = nextPtr;
if (matchIndex <= btLow) largerPtr=&dummy32; /* beyond tree size, stop the search */ matchIndex = nextPtr[0];
matchIndex = (matchIndex <= btLow) ? windowLow : nextPtr[0];
} }
} }
@@ -1213,7 +1221,7 @@ size_t ZSTD_HcFindBestMatch (
const U32 chainSize = (1 << zc->params.contentLog); const U32 chainSize = (1 << zc->params.contentLog);
const U32 minChain = current > chainSize ? current - chainSize : 0; const U32 minChain = current > chainSize ? current - chainSize : 0;
const U32 chainMask = chainSize-1; const U32 chainMask = chainSize-1;
const U32 lowLimit = zc->lowLimit; const U32 lowLimit = zc->dictLimit; /* should be equal to zc->lowLimit, but safer use this one if they are not since dictLimit >= lowLimit */
U32 matchIndex; U32 matchIndex;
const BYTE* match; const BYTE* match;
int nbAttempts=maxNbAttempts; int nbAttempts=maxNbAttempts;
@@ -1230,10 +1238,10 @@ size_t ZSTD_HcFindBestMatch (
{ {
const size_t mlt = ZSTD_count(ip, match, iLimit); const size_t mlt = ZSTD_count(ip, match, iLimit);
if (mlt > ml) if (mlt > ml)
//if (((int)(4*mlt) - (int)ZSTD_highbit((U32)(ip-match)+1)) > ((int)(4*ml) - (int)ZSTD_highbit((U32)((*offsetPtr)+1)))) //if ( (4*(int)(mlt-ml)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)(*offsetPtr) + 1)) ) /* stronger but slower */
{ {
ml = mlt; *offsetPtr = ip-match; ml = mlt; *offsetPtr = ip-match;
if (ip+mlt >= iLimit) break; if (ip+mlt >= iLimit) break; /* max ml possible; avoid risk of reading too far when testing ip[ml] */
} }
} }
@@ -1273,49 +1281,39 @@ size_t ZSTD_HcFindBestMatch_extDict (
const BYTE* const base = zc->base; const BYTE* const base = zc->base;
const BYTE* const dictBase = zc->dictBase; const BYTE* const dictBase = zc->dictBase;
const U32 dictLimit = zc->dictLimit; const U32 dictLimit = zc->dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const U32 lowLimit = zc->lowLimit; const U32 lowLimit = zc->lowLimit;
const U32 current = (U32)(ip-base); const U32 current = (U32)(ip-base);
const U32 minChain = current > chainSize ? current - chainSize : 0; const U32 minChain = current > chainSize ? current - chainSize : 0;
U32 matchIndex; U32 matchIndex;
const BYTE* match; const BYTE* match;
int nbAttempts=maxNbAttempts; int nbAttempts=maxNbAttempts;
size_t ml=0; size_t ml=MINMATCH-1;
/* HC4 match finder */ /* HC4 match finder */
matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, matchLengthSearch); matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, matchLengthSearch);
while ((matchIndex>lowLimit) && (nbAttempts)) while ((matchIndex>lowLimit) && (nbAttempts))
{ {
size_t currentMl=0;
nbAttempts--; nbAttempts--;
if (matchIndex >= dictLimit) if (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);
const size_t mlt = ZSTD_count(ip, match, iLimit);
if (mlt > ml)
//if (((int)(4*mlt) - (int)ZSTD_highbit((U32)(ip-match)+1)) > ((int)(4*ml) - (int)ZSTD_highbit((U32)((*offsetPtr)+1))))
{
ml = mlt; *offsetPtr = ip-match;
if (ip+mlt >= iLimit) break;
}
}
} }
else else
{ {
match = dictBase + matchIndex; match = dictBase + matchIndex;
if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 */ 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;
size_t mlt;
const BYTE* vLimit = ip + (dictLimit - matchIndex);
if (vLimit > iLimit) vLimit = iLimit;
mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
if (match+mlt == dictBase+dictLimit)
mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit);
if (mlt > ml) { ml = mlt; *offsetPtr = current - matchIndex; }
}
} }
/* save best solution */
if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex; }
if (matchIndex <= minChain) break; if (matchIndex <= minChain) break;
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
} }
@@ -1489,7 +1487,7 @@ _storeSequence:
} }
/* Final compression stage */ /* Final compression stage */
return ZSTD_compressSequences((BYTE*)dst, maxDstSize, return ZSTD_compressSequences(dst, maxDstSize,
seqStorePtr, srcSize); seqStorePtr, srcSize);
} }
@@ -1557,16 +1555,12 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
const U32 repIndex = (U32)(current+1 - offset_1); const U32 repIndex = (U32)(current+1 - 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 ((repIndex <= dictLimit-4) || (repIndex >= dictLimit)) 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;
const BYTE* vEnd = ip+1 + (repEnd - repMatch); matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (vEnd > iend) vEnd = iend;
matchLength = ZSTD_count(ip+1+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH;
if (repMatch + matchLength == dictEnd)
matchLength += ZSTD_count(ip+1+matchLength, prefixStart, iend);
if (depth==0) goto _storeSequence; if (depth==0) goto _storeSequence;
} }
} }
@@ -1597,23 +1591,16 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
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 ((repIndex <= dictLimit-4) || (repIndex >= dictLimit)) 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 */
size_t repLength;
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
const BYTE* vEnd = ip + (repEnd - repMatch); size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (vEnd > iend) vEnd = iend; int gain2 = (int)(repLength * 3);
repLength = ZSTD_count(ip+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH; int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
if (repMatch + repLength == dictEnd) if ((repLength >= MINMATCH) && (gain2 > gain1))
repLength += ZSTD_count(ip+repLength, prefixStart, iend); matchLength = repLength, offset = 0, start = ip;
{
int gain2 = (int)(repLength * 3);
int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip;
}
} }
} }
@@ -1641,23 +1628,16 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
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 ((repIndex <= dictLimit-4) || (repIndex >= dictLimit)) 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 */
size_t repLength;
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
const BYTE* vEnd = ip + (repEnd - repMatch); size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (vEnd > iend) vEnd = iend; int gain2 = (int)(repLength * 4);
repLength = ZSTD_count(ip+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH; int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
if (repMatch + repLength == dictEnd) if ((repLength >= MINMATCH) && (gain2 > gain1))
repLength += ZSTD_count(ip+repLength, prefixStart, iend); matchLength = repLength, offset = 0, start = ip;
{
int gain2 = (int)(repLength * 4);
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
if ((repLength >= MINMATCH) && (gain2 > gain1))
matchLength = repLength, offset = 0, start = ip;
}
} }
} }
@@ -1703,14 +1683,8 @@ _storeSequence:
{ {
/* 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;
const BYTE* vEnd = ip + (repEnd - repMatch); matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
if (vEnd > iend) vEnd = iend; offset = offset_2; offset_2 = offset_1; offset_1 = offset; /* swap offset history */
matchLength = ZSTD_count(ip+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH;
if (repMatch + matchLength == dictEnd)
matchLength += ZSTD_count(ip+matchLength, prefixStart, iend);
offset = offset_2;
offset_2 = offset_1;
offset_1 = offset;
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH); ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
ip += matchLength; ip += matchLength;
anchor = ip; anchor = ip;
@@ -1728,7 +1702,7 @@ _storeSequence:
} }
/* Final compression stage */ /* Final compression stage */
return ZSTD_compressSequences((BYTE*)dst, maxDstSize, return ZSTD_compressSequences(dst, maxDstSize,
seqStorePtr, srcSize); seqStorePtr, srcSize);
} }
@@ -1747,6 +1721,12 @@ size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, void* dst, size_t maxDst
return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 0, 2); return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 0, 2);
} }
static size_t ZSTD_compressError(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
(void)ctx; (void)dst; (void)maxDstSize; (void)src; (void)srcSize;
return ERROR(mode_unsupported);
}
typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);
@@ -1766,7 +1746,7 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int
case ZSTD_lazy2: case ZSTD_lazy2:
return ZSTD_compressBlock_lazy2_extDict; return ZSTD_compressBlock_lazy2_extDict;
case ZSTD_btlazy2: case ZSTD_btlazy2:
return ZSTD_compressBlock_btlazy2; return ZSTD_compressError;
} }
} }
else else
@@ -1818,7 +1798,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* ctxPtr,
if ((U32)(ip+blockSize - (ctxPtr->base + ctxPtr->lowLimit)) > maxDist) if ((U32)(ip+blockSize - (ctxPtr->base + ctxPtr->lowLimit)) > maxDist)
/* respect windowLog contract */ /* respect windowLog contract */
ctxPtr->lowLimit = (U32)(ip+blockSize - ctxPtr->base) - maxDist; ctxPtr->dictLimit = ctxPtr->lowLimit = (U32)(ip+blockSize - ctxPtr->base) - maxDist;
//cSize = blockCompressor(ctxPtr, op+3, maxDstSize-3, ip, blockSize); //cSize = blockCompressor(ctxPtr, op+3, maxDstSize-3, ip, blockSize);
cSize = ZSTD_compressBlock(ctxPtr, op+3, maxDstSize-3, ip, blockSize); cSize = ZSTD_compressBlock(ctxPtr, op+3, maxDstSize-3, ip, blockSize);