From: Yann Collet Date: Mon, 23 Nov 2015 12:34:21 +0000 (+0100) Subject: rollbuffer refactor X-Git-Tag: zstd-0.4.0^2~23^2~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5054ee0cc04064f562704c8fe67d08bf71277976;p=thirdparty%2Fzstd.git rollbuffer refactor --- diff --git a/lib/error.h b/lib/error.h index 6afa87f18..68e8d46c3 100644 --- a/lib/error.h +++ b/lib/error.h @@ -68,6 +68,7 @@ extern "C" { #define ERROR_LIST(ITEM) \ ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \ + ITEM(PREFIX(mode_unsupported)) \ ITEM(PREFIX(memory_allocation)) \ ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \ ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \ diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index d98dd6f7b..5c0e7aff3 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -475,7 +475,7 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); MEM_STATIC unsigned BIT_highbit32 (register U32 val) { # if defined(_MSC_VER) /* Visual */ - unsigned long r; + unsigned long r=0; _BitScanReverse ( &r, val ); return (unsigned) r; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c index cfc590a1b..a379c4b84 100644 --- a/lib/zstd_compress.c +++ b/lib/zstd_compress.c @@ -303,7 +303,7 @@ static size_t ZSTD_compressLiterals (void* dst, size_t maxDstSize, #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, size_t srcSize) { @@ -322,8 +322,9 @@ size_t ZSTD_compressSequences(BYTE* dst, size_t maxDstSize, const BYTE* const mlTable = seqStorePtr->matchLengthStart; const U32* const offsetTable = seqStorePtr->offsetStart; BYTE* const offCodeTable = seqStorePtr->offCodeStart; - BYTE* op = dst; - BYTE* const oend = dst + maxDstSize; + BYTE* const ostart = (BYTE*)dst; + BYTE* op = ostart; + BYTE* const oend = ostart + maxDstSize; const size_t nbSeq = llPtr - llTable; const size_t minGain = ZSTD_minGain(srcSize); const size_t maxCSize = srcSize - minGain; @@ -500,9 +501,9 @@ size_t ZSTD_compressSequences(BYTE* dst, size_t maxDstSize, } /* 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 } -MEM_STATIC unsigned ZSTD_NbCommonBytes (register size_t val) +static unsigned ZSTD_NbCommonBytes (register size_t val) { 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; @@ -672,6 +673,21 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pI 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* ip = 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 ilimit = iend - 8; @@ -743,7 +759,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx, /* Main Search Loop */ while (ip < ilimit) /* < instead of <=, because repcode check at (ip+1) */ { - size_t matchLength; + size_t mlCode; size_t offset; const size_t h = ZSTD_hashPtr(ip, hBits, mls); 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)) { - 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++; offset = 0; } @@ -763,22 +779,22 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx, ip += ((ip-anchor) >> g_searchStrength) + 1; continue; } - matchLength = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend); - while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; matchLength++; } /* catch up */ + mlCode = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend); offset = ip-match; + while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; } /* match found */ - ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, matchLength); - ip += matchLength + MINMATCH; + ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode); + hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip+2-base); /* can't use current : ip may have changed */ + ip += mlCode + MINMATCH; anchor = ip; if (ip <= ilimit) { /* 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); /* check immediate repcode */ while ( (ip <= ilimit) @@ -804,7 +820,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* ctx, } /* Finale compression stage */ - return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + return ZSTD_compressSequences(dst, maxDstSize, seqStorePtr, srcSize); } @@ -844,6 +860,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, const BYTE* ip = istart; const BYTE* anchor = istart; const U32 lowLimit = ctx->lowLimit; + const BYTE* const dictStart = dictBase + lowLimit; const U32 dictLimit = ctx->dictLimit; const BYTE* const lowPrefixPtr = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; @@ -870,13 +887,12 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, const size_t h = ZSTD_hashPtr(ip, hBits, mls); const U32 matchIndex = hashTable[h]; const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base; - const BYTE* match = matchBase + matchIndex; - const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictBase + lowLimit : lowPrefixPtr; + const BYTE* match = matchBase + matchIndex; const U32 current = (U32)(ip-base); const U32 repIndex = current + 1 - offset_1; const BYTE* repBase = repIndex < dictLimit ? dictBase : base; const BYTE* repMatch = repBase + repIndex; - size_t matchLength; + size_t mlCode; U32 offset; 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)) ) { const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend; - const BYTE* vEnd = ip+1 + (repMatchEnd-repMatch); - 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); + mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr); ip++; offset = 0; } @@ -899,26 +911,24 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, { ip += ((ip-anchor) >> g_searchStrength) + 1; continue; } { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend; - const BYTE* iEndCount = (matchEnd - match < iend - ip) ? ip + (matchEnd - match) : iend; - matchLength = ZSTD_count(ip+MINMATCH, match+MINMATCH, iEndCount); - if (match + matchLength + MINMATCH == dictEnd) - matchLength += ZSTD_count(ip + matchLength + MINMATCH, lowPrefixPtr, iend); - while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; matchLength++; } /* catch up */ + 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 */ offset = current - matchIndex; offset_2 = offset_1; offset_1 = offset; } } - /* found a match */ - ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, matchLength); - ip += matchLength + MINMATCH; + /* found a match : store it */ + ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode); + hashTable[ZSTD_hashPtr(ip+2, hBits, mls)] = (U32)(ip+2-base); /* can't use current : ip may have changed */ + ip += mlCode + MINMATCH; anchor = ip; if (ip <= ilimit) { - /* Fill Table */ - hashTable[ZSTD_hashPtr(ip-2-matchLength, hBits, mls)] = (U32)(ip-2-matchLength-base); + /* Fill Table */ hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base); /* check immediate repcode */ while (ip <= ilimit) @@ -929,16 +939,12 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit)) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { - size_t maxIlength = iend - ip; - size_t maxMlength = repIndex2 < dictLimit ? (size_t)(dictLimit - repIndex2) : (size_t)(iend - repMatch2); - size_t maxML = MIN(maxMlength, maxIlength); - size_t ml = ZSTD_count(ip+MINMATCH, repMatch2+MINMATCH, ip + maxML); - U32 tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */ - if (ml+MINMATCH == maxMlength) /* reached end of extDict */ - 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; + 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 */ + ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2); + hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2; + ip += repLength2+MINMATCH; anchor = ip; continue; } @@ -955,7 +961,7 @@ size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, } /* Finale compression stage */ - return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + return ZSTD_compressSequences(dst, maxDstSize, 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 */ 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 */ 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; 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 ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) ) bestLength = matchLength, *offsetPtr = current - matchIndex; 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]) @@ -1098,18 +1106,18 @@ size_t ZSTD_insertBtAndFindBestMatch ( /* 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 */ - if (matchIndex <= btLow) smallerPtr=&dummy32; /* beyond tree size, stop the search */ - matchIndex = (matchIndex <= btLow) ? windowLow : nextPtr[1]; + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ } else { /* match is larger than current */ *largerPtr = matchIndex; commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ largerPtr = nextPtr; - if (matchIndex <= btLow) largerPtr=&dummy32; /* beyond tree size, stop the search */ - matchIndex = (matchIndex <= btLow) ? windowLow : nextPtr[0]; + matchIndex = nextPtr[0]; } } @@ -1213,7 +1221,7 @@ size_t ZSTD_HcFindBestMatch ( const U32 chainSize = (1 << zc->params.contentLog); const U32 minChain = current > chainSize ? current - chainSize : 0; 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; const BYTE* match; int nbAttempts=maxNbAttempts; @@ -1230,10 +1238,10 @@ size_t ZSTD_HcFindBestMatch ( { 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)))) + //if ( (4*(int)(mlt-ml)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)(*offsetPtr) + 1)) ) /* stronger but slower */ { 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 dictBase = zc->dictBase; const U32 dictLimit = zc->dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; const U32 lowLimit = zc->lowLimit; const U32 current = (U32)(ip-base); const U32 minChain = current > chainSize ? current - chainSize : 0; U32 matchIndex; const BYTE* match; int nbAttempts=maxNbAttempts; - size_t ml=0; + size_t ml=MINMATCH-1; /* HC4 match finder */ matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, matchLengthSearch); while ((matchIndex>lowLimit) && (nbAttempts)) { + size_t currentMl=0; nbAttempts--; if (matchIndex >= dictLimit) { match = base + matchIndex; if (match[ml] == ip[ml]) /* potentially better */ - { - 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; - } - } + currentMl = ZSTD_count(ip, match, iLimit); } else { match = dictBase + matchIndex; - if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 */ - { - 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; } - } + 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; } + /* save best solution */ + if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex; } + if (matchIndex <= minChain) break; matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); } @@ -1489,7 +1487,7 @@ _storeSequence: } /* Final compression stage */ - return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + return ZSTD_compressSequences(dst, maxDstSize, 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 BYTE* const repBase = repIndex < dictLimit ? dictBase : base; 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)) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - const BYTE* vEnd = ip+1 + (repEnd - repMatch); - 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); + matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; 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 BYTE* const repBase = repIndex < dictLimit ? dictBase : base; 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)) { /* repcode detected */ - size_t repLength; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - const BYTE* vEnd = ip + (repEnd - repMatch); - if (vEnd > iend) vEnd = iend; - repLength = ZSTD_count(ip+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH; - if (repMatch + repLength == dictEnd) - repLength += ZSTD_count(ip+repLength, prefixStart, iend); - { - 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; - } + size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; + 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 BYTE* const repBase = repIndex < dictLimit ? dictBase : base; 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)) { /* repcode detected */ - size_t repLength; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - const BYTE* vEnd = ip + (repEnd - repMatch); - if (vEnd > iend) vEnd = iend; - repLength = ZSTD_count(ip+MINMATCH, repMatch+MINMATCH, vEnd) + MINMATCH; - if (repMatch + repLength == dictEnd) - repLength += ZSTD_count(ip+repLength, prefixStart, iend); - { - 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; - } + size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; + 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 */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - const BYTE* vEnd = ip + (repEnd - repMatch); - if (vEnd > iend) vEnd = iend; - 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; + matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; + offset = offset_2; offset_2 = offset_1; offset_1 = offset; /* swap offset history */ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH); ip += matchLength; anchor = ip; @@ -1728,7 +1702,7 @@ _storeSequence: } /* Final compression stage */ - return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + return ZSTD_compressSequences(dst, maxDstSize, 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); } +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); @@ -1766,7 +1746,7 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int case ZSTD_lazy2: return ZSTD_compressBlock_lazy2_extDict; case ZSTD_btlazy2: - return ZSTD_compressBlock_btlazy2; + return ZSTD_compressError; } } else @@ -1818,7 +1798,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* ctxPtr, if ((U32)(ip+blockSize - (ctxPtr->base + ctxPtr->lowLimit)) > maxDist) /* 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 = ZSTD_compressBlock(ctxPtr, op+3, maxDstSize-3, ip, blockSize);