LCOV - code coverage report
Current view: top level - pression/compressor/zstd/lib/compress - zstd_opt.h (source / functions) Hit Total Coverage
Test: Pression Lines: 0 524 0.0 %
Date: 2016-12-06 05:44:58 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
       3             :  * All rights reserved.
       4             :  *
       5             :  * This source code is licensed under the BSD-style license found in the
       6             :  * LICENSE file in the root directory of this source tree. An additional grant
       7             :  * of patent rights can be found in the PATENTS file in the same directory.
       8             :  */
       9             : 
      10             : 
      11             : /* Note : this file is intended to be included within zstd_compress.c */
      12             : 
      13             : 
      14             : #ifndef ZSTD_OPT_H_91842398743
      15             : #define ZSTD_OPT_H_91842398743
      16             : 
      17             : 
      18             : #define ZSTD_FREQ_DIV   5
      19             : 
      20             : /*-*************************************
      21             : *  Price functions for optimal parser
      22             : ***************************************/
      23             : FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t* ssPtr)
      24             : {
      25           0 :     ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum+1);
      26           0 :     ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum+1);
      27           0 :     ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum+1);
      28           0 :     ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum+1);
      29           0 :     ssPtr->factor = 1 + ((ssPtr->litSum>>5) / ssPtr->litLengthSum) + ((ssPtr->litSum<<1) / (ssPtr->litSum + ssPtr->matchSum));
      30             : }
      31             : 
      32             : 
      33           0 : MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr)
      34             : {
      35             :     unsigned u;
      36             : 
      37           0 :     ssPtr->cachedLiterals = NULL;
      38           0 :     ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
      39             : 
      40           0 :     if (ssPtr->litLengthSum == 0) {
      41           0 :         ssPtr->litSum = (2<<Litbits);
      42           0 :         ssPtr->litLengthSum = MaxLL+1;
      43           0 :         ssPtr->matchLengthSum = MaxML+1;
      44           0 :         ssPtr->offCodeSum = (MaxOff+1);
      45           0 :         ssPtr->matchSum = (2<<Litbits);
      46             : 
      47           0 :         for (u=0; u<=MaxLit; u++)
      48           0 :             ssPtr->litFreq[u] = 2;
      49           0 :         for (u=0; u<=MaxLL; u++)
      50           0 :             ssPtr->litLengthFreq[u] = 1;
      51           0 :         for (u=0; u<=MaxML; u++)
      52           0 :             ssPtr->matchLengthFreq[u] = 1;
      53           0 :         for (u=0; u<=MaxOff; u++)
      54           0 :             ssPtr->offCodeFreq[u] = 1;
      55             :     } else {
      56           0 :         ssPtr->matchLengthSum = 0;
      57           0 :         ssPtr->litLengthSum = 0;
      58           0 :         ssPtr->offCodeSum = 0;
      59           0 :         ssPtr->matchSum = 0;
      60           0 :         ssPtr->litSum = 0;
      61             : 
      62           0 :         for (u=0; u<=MaxLit; u++) {
      63           0 :             ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u]>>ZSTD_FREQ_DIV);
      64           0 :             ssPtr->litSum += ssPtr->litFreq[u];
      65             :         }
      66           0 :         for (u=0; u<=MaxLL; u++) {
      67           0 :             ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u]>>ZSTD_FREQ_DIV);
      68           0 :             ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
      69             :         }
      70           0 :         for (u=0; u<=MaxML; u++) {
      71           0 :             ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
      72           0 :             ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
      73           0 :             ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
      74             :         }
      75           0 :         for (u=0; u<=MaxOff; u++) {
      76           0 :             ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
      77           0 :             ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
      78             :         }
      79             :     }
      80             : 
      81             :     ZSTD_setLog2Prices(ssPtr);
      82           0 : }
      83             : 
      84             : 
      85             : FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* ssPtr, U32 litLength, const BYTE* literals)
      86             : {
      87             :     U32 price, u;
      88             : 
      89           0 :     if (litLength == 0)
      90           0 :         return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0]+1);
      91             : 
      92             :     /* literals */
      93           0 :     if (ssPtr->cachedLiterals == literals) {
      94           0 :         U32 const additional = litLength - ssPtr->cachedLitLength;
      95           0 :         const BYTE* literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength;
      96           0 :         price = ssPtr->cachedPrice + additional * ssPtr->log2litSum;
      97           0 :         for (u=0; u < additional; u++)
      98           0 :             price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]]+1);
      99           0 :         ssPtr->cachedPrice = price;
     100           0 :         ssPtr->cachedLitLength = litLength;
     101             :     } else {
     102           0 :         price = litLength * ssPtr->log2litSum;
     103           0 :         for (u=0; u < litLength; u++)
     104           0 :             price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]]+1);
     105             : 
     106           0 :         if (litLength >= 12) {
     107           0 :             ssPtr->cachedLiterals = literals;
     108           0 :             ssPtr->cachedPrice = price;
     109           0 :             ssPtr->cachedLitLength = litLength;
     110             :         }
     111             :     }
     112             : 
     113             :     /* literal Length */
     114           0 :     {   const BYTE LL_deltaCode = 19;
     115           0 :         const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
     116           0 :         price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode]+1);
     117             :     }
     118             : 
     119           0 :     return price;
     120             : }
     121             : 
     122             : 
     123             : FORCE_INLINE U32 ZSTD_getPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
     124             : {
     125             :     /* offset */
     126           0 :     BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
     127           0 :     U32 price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode]+1);
     128             : 
     129             :     /* match Length */
     130           0 :     {   const BYTE ML_deltaCode = 36;
     131           0 :         const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
     132           0 :         price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode]+1);
     133             :     }
     134             : 
     135           0 :     return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
     136             : }
     137             : 
     138             : 
     139           0 : MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
     140             : {
     141             :     U32 u;
     142             : 
     143             :     /* literals */
     144           0 :     seqStorePtr->litSum += litLength;
     145           0 :     for (u=0; u < litLength; u++)
     146           0 :         seqStorePtr->litFreq[literals[u]]++;
     147             : 
     148             :     /* literal Length */
     149           0 :     {   const BYTE LL_deltaCode = 19;
     150           0 :         const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
     151           0 :         seqStorePtr->litLengthFreq[llCode]++;
     152           0 :         seqStorePtr->litLengthSum++;
     153             :     }
     154             : 
     155             :     /* match offset */
     156           0 :         {   BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
     157           0 :                 seqStorePtr->offCodeSum++;
     158           0 :                 seqStorePtr->offCodeFreq[offCode]++;
     159             :         }
     160             : 
     161             :     /* match Length */
     162           0 :     {   const BYTE ML_deltaCode = 36;
     163           0 :         const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
     164           0 :         seqStorePtr->matchLengthFreq[mlCode]++;
     165           0 :         seqStorePtr->matchLengthSum++;
     166             :     }
     167             : 
     168             :     ZSTD_setLog2Prices(seqStorePtr);
     169           0 : }
     170             : 
     171             : 
     172             : #define SET_PRICE(pos, mlen_, offset_, litlen_, price_)   \
     173             :     {                                                 \
     174             :         while (last_pos < pos)  { opt[last_pos+1].price = 1<<30; last_pos++; } \
     175             :         opt[pos].mlen = mlen_;                         \
     176             :         opt[pos].off = offset_;                        \
     177             :         opt[pos].litlen = litlen_;                     \
     178             :         opt[pos].price = price_;                       \
     179             :     }
     180             : 
     181             : 
     182             : 
     183             : /* Update hashTable3 up to ip (excluded)
     184             :    Assumption : always within prefix (ie. not within extDict) */
     185             : FORCE_INLINE
     186             : U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
     187             : {
     188           0 :     U32* const hashTable3  = zc->hashTable3;
     189           0 :     U32 const hashLog3  = zc->hashLog3;
     190           0 :     const BYTE* const base = zc->base;
     191           0 :     U32 idx = zc->nextToUpdate3;
     192           0 :     const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
     193           0 :     const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
     194             : 
     195           0 :     while(idx < target) {
     196           0 :         hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
     197           0 :         idx++;
     198             :     }
     199             : 
     200           0 :     return hashTable3[hash3];
     201             : }
     202             : 
     203             : 
     204             : /*-*************************************
     205             : *  Binary Tree search
     206             : ***************************************/
     207           0 : static U32 ZSTD_insertBtAndGetAllMatches (
     208             :                         ZSTD_CCtx* zc,
     209             :                         const BYTE* const ip, const BYTE* const iLimit,
     210             :                         U32 nbCompares, const U32 mls,
     211             :                         U32 extDict, ZSTD_match_t* matches, const U32 minMatchLen)
     212             : {
     213           0 :     const BYTE* const base = zc->base;
     214           0 :     const U32 current = (U32)(ip-base);
     215           0 :     const U32 hashLog = zc->params.cParams.hashLog;
     216           0 :     const size_t h  = ZSTD_hashPtr(ip, hashLog, mls);
     217           0 :     U32* const hashTable = zc->hashTable;
     218           0 :     U32 matchIndex  = hashTable[h];
     219           0 :     U32* const bt   = zc->chainTable;
     220           0 :     const U32 btLog = zc->params.cParams.chainLog - 1;
     221           0 :     const U32 btMask= (1U << btLog) - 1;
     222           0 :     size_t commonLengthSmaller=0, commonLengthLarger=0;
     223           0 :     const BYTE* const dictBase = zc->dictBase;
     224           0 :     const U32 dictLimit = zc->dictLimit;
     225           0 :     const BYTE* const dictEnd = dictBase + dictLimit;
     226           0 :     const BYTE* const prefixStart = base + dictLimit;
     227           0 :     const U32 btLow = btMask >= current ? 0 : current - btMask;
     228           0 :     const U32 windowLow = zc->lowLimit;
     229           0 :     U32* smallerPtr = bt + 2*(current&btMask);
     230           0 :     U32* largerPtr  = bt + 2*(current&btMask) + 1;
     231           0 :     U32 matchEndIdx = current+8;
     232             :     U32 dummy32;   /* to be nullified at the end */
     233           0 :     U32 mnum = 0;
     234             : 
     235           0 :     const U32 minMatch = (mls == 3) ? 3 : 4;
     236           0 :     size_t bestLength = minMatchLen-1;
     237             : 
     238           0 :     if (minMatch == 3) { /* HC3 match finder */
     239           0 :         U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
     240           0 :         if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
     241             :             const BYTE* match;
     242           0 :             size_t currentMl=0;
     243           0 :             if ((!extDict) || matchIndex3 >= dictLimit) {
     244           0 :                 match = base + matchIndex3;
     245           0 :                 if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
     246             :             } else {
     247           0 :                 match = dictBase + matchIndex3;
     248           0 :                 if (MEM_readMINMATCH(match, MINMATCH) == MEM_readMINMATCH(ip, MINMATCH))    /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
     249           0 :                     currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
     250             :             }
     251             : 
     252             :             /* save best solution */
     253           0 :             if (currentMl > bestLength) {
     254           0 :                 bestLength = currentMl;
     255           0 :                 matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3;
     256           0 :                 matches[mnum].len = (U32)currentMl;
     257           0 :                 mnum++;
     258           0 :                 if (currentMl > ZSTD_OPT_NUM) goto update;
     259           0 :                 if (ip+currentMl == iLimit) goto update; /* best possible, and avoid read overflow*/
     260             :             }
     261             :         }
     262             :     }
     263             : 
     264           0 :     hashTable[h] = current;   /* Update Hash Table */
     265             : 
     266           0 :     while (nbCompares-- && (matchIndex > windowLow)) {
     267           0 :         U32* nextPtr = bt + 2*(matchIndex & btMask);
     268           0 :         size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */
     269             :         const BYTE* match;
     270             : 
     271           0 :         if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
     272           0 :             match = base + matchIndex;
     273           0 :             if (match[matchLength] == ip[matchLength]) {
     274           0 :                 matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
     275             :             }
     276             :         } else {
     277           0 :             match = dictBase + matchIndex;
     278           0 :             matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
     279           0 :             if (matchIndex+matchLength >= dictLimit)
     280           0 :                 match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */
     281             :         }
     282             : 
     283           0 :         if (matchLength > bestLength) {
     284           0 :             if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
     285           0 :             bestLength = matchLength;
     286           0 :             matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex;
     287           0 :             matches[mnum].len = (U32)matchLength;
     288           0 :             mnum++;
     289           0 :             if (matchLength > ZSTD_OPT_NUM) break;
     290           0 :             if (ip+matchLength == iLimit)   /* equal : no way to know if inf or sup */
     291           0 :                 break;   /* drop, to guarantee consistency (miss a little bit of compression) */
     292             :         }
     293             : 
     294           0 :         if (match[matchLength] < ip[matchLength]) {
     295             :             /* match is smaller than current */
     296           0 :             *smallerPtr = matchIndex;             /* update smaller idx */
     297           0 :             commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */
     298           0 :             if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */
     299           0 :             smallerPtr = nextPtr+1;               /* new "smaller" => larger of match */
     300           0 :             matchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */
     301             :         } else {
     302             :             /* match is larger than current */
     303           0 :             *largerPtr = matchIndex;
     304           0 :             commonLengthLarger = matchLength;
     305           0 :             if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */
     306           0 :             largerPtr = nextPtr;
     307           0 :             matchIndex = nextPtr[0];
     308             :     }   }
     309             : 
     310           0 :     *smallerPtr = *largerPtr = 0;
     311             : 
     312             : update:
     313           0 :     zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
     314           0 :     return mnum;
     315             : }
     316             : 
     317             : 
     318             : /** Tree updater, providing best match */
     319           0 : static U32 ZSTD_BtGetAllMatches (
     320             :                         ZSTD_CCtx* zc,
     321             :                         const BYTE* const ip, const BYTE* const iLimit,
     322             :                         const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
     323             : {
     324           0 :     if (ip < zc->base + zc->nextToUpdate) return 0;   /* skipped area */
     325           0 :     ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
     326           0 :     return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
     327             : }
     328             : 
     329             : 
     330           0 : static U32 ZSTD_BtGetAllMatches_selectMLS (
     331             :                         ZSTD_CCtx* zc,   /* Index table will be updated */
     332             :                         const BYTE* ip, const BYTE* const iHighLimit,
     333             :                         const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
     334             : {
     335           0 :     switch(matchLengthSearch)
     336             :     {
     337           0 :     case 3 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
     338             :     default :
     339           0 :     case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
     340           0 :     case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
     341           0 :     case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
     342             :     }
     343             : }
     344             : 
     345             : /** Tree updater, providing best match */
     346           0 : static U32 ZSTD_BtGetAllMatches_extDict (
     347             :                         ZSTD_CCtx* zc,
     348             :                         const BYTE* const ip, const BYTE* const iLimit,
     349             :                         const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
     350             : {
     351           0 :     if (ip < zc->base + zc->nextToUpdate) return 0;   /* skipped area */
     352           0 :     ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
     353           0 :     return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
     354             : }
     355             : 
     356             : 
     357           0 : static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
     358             :                         ZSTD_CCtx* zc,   /* Index table will be updated */
     359             :                         const BYTE* ip, const BYTE* const iHighLimit,
     360             :                         const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
     361             : {
     362           0 :     switch(matchLengthSearch)
     363             :     {
     364           0 :     case 3 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
     365             :     default :
     366           0 :     case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
     367           0 :     case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
     368           0 :     case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
     369             :     }
     370             : }
     371             : 
     372             : 
     373             : /*-*******************************
     374             : *  Optimal parser
     375             : *********************************/
     376             : FORCE_INLINE
     377             : void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
     378             :                                     const void* src, size_t srcSize)
     379             : {
     380           0 :     seqStore_t* seqStorePtr = &(ctx->seqStore);
     381           0 :     const BYTE* const istart = (const BYTE*)src;
     382           0 :     const BYTE* ip = istart;
     383           0 :     const BYTE* anchor = istart;
     384           0 :     const BYTE* const iend = istart + srcSize;
     385           0 :     const BYTE* const ilimit = iend - 8;
     386           0 :     const BYTE* const base = ctx->base;
     387           0 :     const BYTE* const prefixStart = base + ctx->dictLimit;
     388             : 
     389           0 :     const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
     390           0 :     const U32 sufficient_len = ctx->params.cParams.targetLength;
     391           0 :     const U32 mls = ctx->params.cParams.searchLength;
     392           0 :     const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
     393             : 
     394           0 :     ZSTD_optimal_t* opt = seqStorePtr->priceTable;
     395           0 :     ZSTD_match_t* matches = seqStorePtr->matchTable;
     396             :     const BYTE* inr;
     397             :     U32 offset, rep[ZSTD_REP_NUM];
     398             : 
     399             :     /* init */
     400           0 :     ctx->nextToUpdate3 = ctx->nextToUpdate;
     401           0 :     ZSTD_rescaleFreqs(seqStorePtr);
     402           0 :     ip += (ip==prefixStart);
     403           0 :     { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=ctx->rep[i]; }
     404           0 :     inr = ip;
     405             : 
     406             :     /* Match Loop */
     407           0 :     while (ip < ilimit) {
     408             :         U32 cur, match_num, last_pos, litlen, price;
     409             :         U32 u, mlen, best_mlen, best_off, litLength;
     410           0 :         memset(opt, 0, sizeof(ZSTD_optimal_t));
     411           0 :         last_pos = 0;
     412           0 :         litlen = (U32)(ip - anchor);
     413             : 
     414             :         /* check repCode */
     415           0 :         {   U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
     416           0 :             for (i=(ip == anchor); i<last_i; i++) {
     417           0 :                 const S32 repCur = ((i==ZSTD_REP_MOVE_OPT) && (ip==anchor)) ? (rep[0] - 1) : rep[i];
     418           0 :                 if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
     419           0 :                     && (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(ip - repCur, minMatch))) {
     420           0 :                     mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
     421           0 :                     if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
     422           0 :                         best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
     423             :                         goto _storeSequence;
     424             :                     }
     425           0 :                     best_off = i - (ip == anchor);
     426             :                     do {
     427           0 :                         price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH);
     428           0 :                         if (mlen > last_pos || price < opt[mlen].price)
     429           0 :                             SET_PRICE(mlen, mlen, i, litlen, price);   /* note : macro modifies last_pos */
     430           0 :                         mlen--;
     431           0 :                     } while (mlen >= minMatch);
     432             :         }   }   }
     433             : 
     434           0 :         match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
     435             : 
     436           0 :         if (!last_pos && !match_num) { ip++; continue; }
     437             : 
     438           0 :         if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
     439           0 :             best_mlen = matches[match_num-1].len;
     440           0 :             best_off = matches[match_num-1].off;
     441           0 :             cur = 0;
     442           0 :             last_pos = 1;
     443             :             goto _storeSequence;
     444             :         }
     445             : 
     446             :         /* set prices using matches at position = 0 */
     447           0 :         best_mlen = (last_pos) ? last_pos : minMatch;
     448           0 :         for (u = 0; u < match_num; u++) {
     449           0 :             mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
     450           0 :             best_mlen = matches[u].len;
     451           0 :             while (mlen <= best_mlen) {
     452           0 :                 price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH);
     453           0 :                 if (mlen > last_pos || price < opt[mlen].price)
     454           0 :                     SET_PRICE(mlen, mlen, matches[u].off, litlen, price);   /* note : macro modifies last_pos */
     455           0 :                 mlen++;
     456             :         }   }
     457             : 
     458           0 :         if (last_pos < minMatch) { ip++; continue; }
     459             : 
     460             :         /* initialize opt[0] */
     461           0 :         { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
     462           0 :         opt[0].mlen = 1;
     463           0 :         opt[0].litlen = litlen;
     464             : 
     465             :          /* check further positions */
     466           0 :         for (cur = 1; cur <= last_pos; cur++) {
     467           0 :            inr = ip + cur;
     468             : 
     469           0 :            if (opt[cur-1].mlen == 1) {
     470           0 :                 litlen = opt[cur-1].litlen + 1;
     471           0 :                 if (cur > litlen) {
     472           0 :                     price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
     473             :                 } else
     474           0 :                     price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
     475             :            } else {
     476           0 :                 litlen = 1;
     477           0 :                 price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
     478             :            }
     479             : 
     480           0 :            if (cur > last_pos || price <= opt[cur].price)
     481           0 :                 SET_PRICE(cur, 1, 0, litlen, price);
     482             : 
     483           0 :            if (cur == last_pos) break;
     484             : 
     485           0 :            if (inr > ilimit)  /* last match must start at a minimum distance of 8 from oend */
     486           0 :                continue;
     487             : 
     488           0 :            mlen = opt[cur].mlen;
     489           0 :            if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
     490           0 :                 opt[cur].rep[2] = opt[cur-mlen].rep[1];
     491           0 :                 opt[cur].rep[1] = opt[cur-mlen].rep[0];
     492           0 :                 opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
     493             :            } else {
     494           0 :                 opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
     495           0 :                 opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
     496           0 :                 opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
     497             :            }
     498             : 
     499           0 :            best_mlen = minMatch;
     500           0 :             {   U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
     501           0 :                 for (i=(opt[cur].mlen != 1); i<last_i; i++) {  /* check rep */
     502           0 :                     const S32 repCur = ((i==ZSTD_REP_MOVE_OPT) && (opt[cur].mlen != 1)) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
     503           0 :                     if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
     504           0 :                        && (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(inr - repCur, minMatch))) {
     505           0 :                        mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
     506             : 
     507           0 :                        if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
     508           0 :                             best_mlen = mlen; best_off = i; last_pos = cur + 1;
     509             :                             goto _storeSequence;
     510             :                        }
     511             : 
     512           0 :                        best_off = i - (opt[cur].mlen != 1);
     513             : 
     514           0 :                        if (opt[cur].mlen == 1) {
     515           0 :                             litlen = opt[cur].litlen;
     516           0 :                             if (cur > litlen) {
     517           0 :                                 price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, best_off, mlen - MINMATCH);
     518             :                             } else
     519           0 :                                 price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH);
     520             :                         } else {
     521           0 :                             litlen = 0;
     522           0 :                             price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH);
     523             :                         }
     524             : 
     525           0 :                         if (mlen > best_mlen) best_mlen = mlen;
     526             : 
     527             :                         do {
     528           0 :                             if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
     529           0 :                                 SET_PRICE(cur + mlen, mlen, i, litlen, price);
     530           0 :                             mlen--;
     531           0 :                         } while (mlen >= minMatch);
     532             :             }   }   }
     533             : 
     534           0 :             match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
     535             : 
     536           0 :             if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
     537           0 :                 best_mlen = matches[match_num-1].len;
     538           0 :                 best_off = matches[match_num-1].off;
     539           0 :                 last_pos = cur + 1;
     540             :                 goto _storeSequence;
     541             :             }
     542             : 
     543             :             /* set prices using matches at position = cur */
     544           0 :             for (u = 0; u < match_num; u++) {
     545           0 :                 mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
     546           0 :                 best_mlen = matches[u].len;
     547             : 
     548           0 :                 while (mlen <= best_mlen) {
     549           0 :                     if (opt[cur].mlen == 1) {
     550           0 :                         litlen = opt[cur].litlen;
     551           0 :                         if (cur > litlen)
     552           0 :                             price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH);
     553             :                         else
     554           0 :                             price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH);
     555             :                     } else {
     556           0 :                         litlen = 0;
     557           0 :                         price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH);
     558             :                     }
     559             : 
     560           0 :                     if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
     561           0 :                         SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
     562             : 
     563           0 :                     mlen++;
     564             :         }   }   }
     565             : 
     566           0 :         best_mlen = opt[last_pos].mlen;
     567           0 :         best_off = opt[last_pos].off;
     568           0 :         cur = last_pos - best_mlen;
     569             : 
     570             :         /* store sequence */
     571             : _storeSequence:   /* cur, last_pos, best_mlen, best_off have to be set */
     572           0 :         opt[0].mlen = 1;
     573             : 
     574             :         while (1) {
     575           0 :             mlen = opt[cur].mlen;
     576           0 :             offset = opt[cur].off;
     577           0 :             opt[cur].mlen = best_mlen;
     578           0 :             opt[cur].off = best_off;
     579           0 :             best_mlen = mlen;
     580           0 :             best_off = offset;
     581           0 :             if (mlen > cur) break;
     582           0 :             cur -= mlen;
     583             :         }
     584             : 
     585           0 :         for (u = 0; u <= last_pos;) {
     586           0 :             u += opt[u].mlen;
     587             :         }
     588             : 
     589           0 :         for (cur=0; cur < last_pos; ) {
     590           0 :             mlen = opt[cur].mlen;
     591           0 :             if (mlen == 1) { ip++; cur++; continue; }
     592           0 :             offset = opt[cur].off;
     593           0 :             cur += mlen;
     594           0 :             litLength = (U32)(ip - anchor);
     595             : 
     596           0 :             if (offset > ZSTD_REP_MOVE_OPT) {
     597           0 :                 rep[2] = rep[1];
     598           0 :                 rep[1] = rep[0];
     599           0 :                 rep[0] = offset - ZSTD_REP_MOVE_OPT;
     600           0 :                 offset--;
     601             :             } else {
     602           0 :                 if (offset != 0) {
     603           0 :                     best_off = ((offset==ZSTD_REP_MOVE_OPT) && (litLength==0)) ? (rep[0] - 1) : (rep[offset]);
     604           0 :                     if (offset != 1) rep[2] = rep[1];
     605           0 :                     rep[1] = rep[0];
     606           0 :                     rep[0] = best_off;
     607             :                 }
     608           0 :                 if (litLength==0) offset--;
     609             :             }
     610             : 
     611           0 :             ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
     612           0 :             ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
     613           0 :             anchor = ip = ip + mlen;
     614             :     }    }   /* for (cur=0; cur < last_pos; ) */
     615             : 
     616             :     /* Save reps for next block */
     617           0 :     { int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->savedRep[i] = rep[i]; }
     618             : 
     619             :     /* Last Literals */
     620           0 :     {   size_t const lastLLSize = iend - anchor;
     621           0 :         memcpy(seqStorePtr->lit, anchor, lastLLSize);
     622           0 :         seqStorePtr->lit += lastLLSize;
     623             :     }
     624             : }
     625             : 
     626             : 
     627             : FORCE_INLINE
     628             : void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
     629             :                                      const void* src, size_t srcSize)
     630             : {
     631           0 :     seqStore_t* seqStorePtr = &(ctx->seqStore);
     632           0 :     const BYTE* const istart = (const BYTE*)src;
     633           0 :     const BYTE* ip = istart;
     634           0 :     const BYTE* anchor = istart;
     635           0 :     const BYTE* const iend = istart + srcSize;
     636           0 :     const BYTE* const ilimit = iend - 8;
     637           0 :     const BYTE* const base = ctx->base;
     638           0 :     const U32 lowestIndex = ctx->lowLimit;
     639           0 :     const U32 dictLimit = ctx->dictLimit;
     640           0 :     const BYTE* const prefixStart = base + dictLimit;
     641           0 :     const BYTE* const dictBase = ctx->dictBase;
     642           0 :     const BYTE* const dictEnd  = dictBase + dictLimit;
     643             : 
     644           0 :     const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
     645           0 :     const U32 sufficient_len = ctx->params.cParams.targetLength;
     646           0 :     const U32 mls = ctx->params.cParams.searchLength;
     647           0 :     const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
     648             : 
     649           0 :     ZSTD_optimal_t* opt = seqStorePtr->priceTable;
     650           0 :     ZSTD_match_t* matches = seqStorePtr->matchTable;
     651             :     const BYTE* inr;
     652             : 
     653             :     /* init */
     654             :     U32 offset, rep[ZSTD_REP_NUM];
     655           0 :     { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=ctx->rep[i]; }
     656             : 
     657           0 :     ctx->nextToUpdate3 = ctx->nextToUpdate;
     658           0 :     ZSTD_rescaleFreqs(seqStorePtr);
     659           0 :     ip += (ip==prefixStart);
     660           0 :     inr = ip;
     661             : 
     662             :     /* Match Loop */
     663           0 :     while (ip < ilimit) {
     664             :         U32 cur, match_num, last_pos, litlen, price;
     665             :         U32 u, mlen, best_mlen, best_off, litLength;
     666           0 :         U32 current = (U32)(ip-base);
     667           0 :         memset(opt, 0, sizeof(ZSTD_optimal_t));
     668           0 :         last_pos = 0;
     669           0 :         inr = ip;
     670           0 :         opt[0].litlen = (U32)(ip - anchor);
     671             : 
     672             :         /* check repCode */
     673           0 :         {   U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
     674           0 :             for (i = (ip==anchor); i<last_i; i++) {
     675           0 :                 const S32 repCur = ((i==ZSTD_REP_MOVE_OPT) && (ip==anchor)) ? (rep[0] - 1) : rep[i];
     676           0 :                 const U32 repIndex = (U32)(current - repCur);
     677           0 :                 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
     678           0 :                 const BYTE* const repMatch = repBase + repIndex;
     679           0 :                 if ( (repCur > 0 && repCur <= (S32)current)
     680           0 :                    && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex))  /* intentional overflow */
     681           0 :                    && (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
     682             :                     /* repcode detected we should take it */
     683           0 :                     const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
     684           0 :                     mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
     685             : 
     686           0 :                     if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
     687           0 :                         best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
     688             :                         goto _storeSequence;
     689             :                     }
     690             : 
     691           0 :                     best_off = i - (ip==anchor);
     692           0 :                     litlen = opt[0].litlen;
     693             :                     do {
     694           0 :                         price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH);
     695           0 :                         if (mlen > last_pos || price < opt[mlen].price)
     696           0 :                             SET_PRICE(mlen, mlen, i, litlen, price);   /* note : macro modifies last_pos */
     697           0 :                         mlen--;
     698           0 :                     } while (mlen >= minMatch);
     699             :         }   }   }
     700             : 
     701           0 :         match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch);  /* first search (depth 0) */
     702             : 
     703           0 :         if (!last_pos && !match_num) { ip++; continue; }
     704             : 
     705           0 :         { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
     706           0 :         opt[0].mlen = 1;
     707             : 
     708           0 :         if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
     709           0 :             best_mlen = matches[match_num-1].len;
     710           0 :             best_off = matches[match_num-1].off;
     711           0 :             cur = 0;
     712           0 :             last_pos = 1;
     713             :             goto _storeSequence;
     714             :         }
     715             : 
     716           0 :         best_mlen = (last_pos) ? last_pos : minMatch;
     717             : 
     718             :         /* set prices using matches at position = 0 */
     719           0 :         for (u = 0; u < match_num; u++) {
     720           0 :             mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
     721           0 :             best_mlen = matches[u].len;
     722           0 :             litlen = opt[0].litlen;
     723           0 :             while (mlen <= best_mlen) {
     724           0 :                 price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH);
     725           0 :                 if (mlen > last_pos || price < opt[mlen].price)
     726           0 :                     SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
     727           0 :                 mlen++;
     728             :         }   }
     729             : 
     730           0 :         if (last_pos < minMatch) {
     731           0 :             ip++; continue;
     732             :         }
     733             : 
     734             :         /* check further positions */
     735           0 :         for (cur = 1; cur <= last_pos; cur++) {
     736           0 :             inr = ip + cur;
     737             : 
     738           0 :             if (opt[cur-1].mlen == 1) {
     739           0 :                 litlen = opt[cur-1].litlen + 1;
     740           0 :                 if (cur > litlen) {
     741           0 :                     price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
     742             :                 } else
     743           0 :                     price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
     744             :             } else {
     745           0 :                 litlen = 1;
     746           0 :                 price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
     747             :             }
     748             : 
     749           0 :             if (cur > last_pos || price <= opt[cur].price)
     750           0 :                 SET_PRICE(cur, 1, 0, litlen, price);
     751             : 
     752           0 :             if (cur == last_pos) break;
     753             : 
     754           0 :             if (inr > ilimit)  /* last match must start at a minimum distance of 8 from oend */
     755           0 :                 continue;
     756             : 
     757           0 :             mlen = opt[cur].mlen;
     758           0 :             if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
     759           0 :                 opt[cur].rep[2] = opt[cur-mlen].rep[1];
     760           0 :                 opt[cur].rep[1] = opt[cur-mlen].rep[0];
     761           0 :                 opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
     762             :             } else {
     763           0 :                 opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
     764           0 :                 opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
     765           0 :                 opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
     766             :             }
     767             : 
     768           0 :             best_mlen = 0;
     769             : 
     770           0 :             {   U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
     771           0 :                 for (i = (mlen != 1); i<last_i; i++) {
     772           0 :                     const S32 repCur = ((i==ZSTD_REP_MOVE_OPT) && (opt[cur].mlen != 1)) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
     773           0 :                     const U32 repIndex = (U32)(current+cur - repCur);
     774           0 :                     const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
     775           0 :                     const BYTE* const repMatch = repBase + repIndex;
     776           0 :                     if ( (repCur > 0 && repCur <= (S32)(current+cur))
     777           0 :                       && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex))  /* intentional overflow */
     778           0 :                       && (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
     779             :                         /* repcode detected */
     780           0 :                         const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
     781           0 :                         mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
     782             : 
     783           0 :                         if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
     784           0 :                             best_mlen = mlen; best_off = i; last_pos = cur + 1;
     785             :                             goto _storeSequence;
     786             :                         }
     787             : 
     788           0 :                         best_off = i - (opt[cur].mlen != 1);
     789           0 :                         if (opt[cur].mlen == 1) {
     790           0 :                             litlen = opt[cur].litlen;
     791           0 :                             if (cur > litlen) {
     792           0 :                                 price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, best_off, mlen - MINMATCH);
     793             :                             } else
     794           0 :                                 price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH);
     795             :                         } else {
     796           0 :                             litlen = 0;
     797           0 :                             price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH);
     798             :                         }
     799             : 
     800           0 :                         best_mlen = mlen;
     801             : 
     802             :                         do {
     803           0 :                             if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
     804           0 :                                 SET_PRICE(cur + mlen, mlen, i, litlen, price);
     805           0 :                             mlen--;
     806           0 :                         } while (mlen >= minMatch);
     807             :             }   }   }
     808             : 
     809           0 :             match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
     810             : 
     811           0 :             if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
     812           0 :                 best_mlen = matches[match_num-1].len;
     813           0 :                 best_off = matches[match_num-1].off;
     814           0 :                 last_pos = cur + 1;
     815             :                 goto _storeSequence;
     816             :             }
     817             : 
     818           0 :             best_mlen = (best_mlen > minMatch) ? best_mlen : minMatch;
     819             : 
     820             :             /* set prices using matches at position = cur */
     821           0 :             for (u = 0; u < match_num; u++) {
     822           0 :                 mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
     823           0 :                 best_mlen = (cur + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur;
     824             : 
     825           0 :                 while (mlen <= best_mlen) {
     826           0 :                     if (opt[cur].mlen == 1) {
     827           0 :                         litlen = opt[cur].litlen;
     828           0 :                         if (cur > litlen)
     829           0 :                             price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH);
     830             :                         else
     831           0 :                             price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH);
     832             :                     } else {
     833           0 :                         litlen = 0;
     834           0 :                         price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH);
     835             :                     }
     836             : 
     837           0 :                     if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
     838           0 :                         SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
     839             : 
     840           0 :                     mlen++;
     841             :         }   }   }   /* for (cur = 1; cur <= last_pos; cur++) */
     842             : 
     843           0 :         best_mlen = opt[last_pos].mlen;
     844           0 :         best_off = opt[last_pos].off;
     845           0 :         cur = last_pos - best_mlen;
     846             : 
     847             :         /* store sequence */
     848             : _storeSequence:   /* cur, last_pos, best_mlen, best_off have to be set */
     849           0 :         opt[0].mlen = 1;
     850             : 
     851             :         while (1) {
     852           0 :             mlen = opt[cur].mlen;
     853           0 :             offset = opt[cur].off;
     854           0 :             opt[cur].mlen = best_mlen;
     855           0 :             opt[cur].off = best_off;
     856           0 :             best_mlen = mlen;
     857           0 :             best_off = offset;
     858           0 :             if (mlen > cur) break;
     859           0 :             cur -= mlen;
     860             :         }
     861             : 
     862           0 :         for (u = 0; u <= last_pos; ) {
     863           0 :             u += opt[u].mlen;
     864             :         }
     865             : 
     866           0 :         for (cur=0; cur < last_pos; ) {
     867           0 :             mlen = opt[cur].mlen;
     868           0 :             if (mlen == 1) { ip++; cur++; continue; }
     869           0 :             offset = opt[cur].off;
     870           0 :             cur += mlen;
     871           0 :             litLength = (U32)(ip - anchor);
     872             : 
     873           0 :             if (offset > ZSTD_REP_MOVE_OPT) {
     874           0 :                 rep[2] = rep[1];
     875           0 :                 rep[1] = rep[0];
     876           0 :                 rep[0] = offset - ZSTD_REP_MOVE_OPT;
     877           0 :                 offset--;
     878             :             } else {
     879           0 :                 if (offset != 0) {
     880           0 :                     best_off = ((offset==ZSTD_REP_MOVE_OPT) && (litLength==0)) ? (rep[0] - 1) : (rep[offset]);
     881           0 :                     if (offset != 1) rep[2] = rep[1];
     882           0 :                     rep[1] = rep[0];
     883           0 :                     rep[0] = best_off;
     884             :                 }
     885             : 
     886           0 :                 if (litLength==0) offset--;
     887             :             }
     888             : 
     889           0 :             ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
     890           0 :             ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
     891           0 :             anchor = ip = ip + mlen;
     892             :     }    }   /* for (cur=0; cur < last_pos; ) */
     893             : 
     894             :     /* Save reps for next block */
     895           0 :     { int i; for (i=0; i<ZSTD_REP_NUM; i++) ctx->savedRep[i] = rep[i]; }
     896             : 
     897             :     /* Last Literals */
     898           0 :     {   size_t lastLLSize = iend - anchor;
     899           0 :         memcpy(seqStorePtr->lit, anchor, lastLLSize);
     900           0 :         seqStorePtr->lit += lastLLSize;
     901             :     }
     902             : }
     903             : 
     904             : #endif  /* ZSTD_OPT_H_91842398743 */

Generated by: LCOV version 1.11