zstd_opt.c 39 KB

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