zstd_opt.h 33 KB

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