zstd_ldm.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. /*
  2. * Copyright (c) 2016-present, 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. */
  9. #include "zstd_ldm.h"
  10. #include "zstd_fast.h" /* ZSTD_fillHashTable() */
  11. #include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
  12. #define LDM_BUCKET_SIZE_LOG 3
  13. #define LDM_MIN_MATCH_LENGTH 64
  14. #define LDM_HASH_RLOG 7
  15. #define LDM_HASH_CHAR_OFFSET 10
  16. size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm)
  17. {
  18. ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);
  19. params->enableLdm = enableLdm>0;
  20. params->hashLog = 0;
  21. params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
  22. params->minMatchLength = LDM_MIN_MATCH_LENGTH;
  23. params->hashEveryLog = ZSTD_LDM_HASHEVERYLOG_NOTSET;
  24. return 0;
  25. }
  26. void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog)
  27. {
  28. if (params->hashLog == 0) {
  29. params->hashLog = MAX(ZSTD_HASHLOG_MIN, windowLog - LDM_HASH_RLOG);
  30. assert(params->hashLog <= ZSTD_HASHLOG_MAX);
  31. }
  32. if (params->hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET) {
  33. params->hashEveryLog =
  34. windowLog < params->hashLog ? 0 : windowLog - params->hashLog;
  35. }
  36. params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);
  37. }
  38. size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog) {
  39. size_t const ldmHSize = ((size_t)1) << hashLog;
  40. size_t const ldmBucketSizeLog = MIN(bucketSizeLog, hashLog);
  41. size_t const ldmBucketSize =
  42. ((size_t)1) << (hashLog - ldmBucketSizeLog);
  43. return ldmBucketSize + (ldmHSize * (sizeof(ldmEntry_t)));
  44. }
  45. /** ZSTD_ldm_getSmallHash() :
  46. * numBits should be <= 32
  47. * If numBits==0, returns 0.
  48. * @return : the most significant numBits of value. */
  49. static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits)
  50. {
  51. assert(numBits <= 32);
  52. return numBits == 0 ? 0 : (U32)(value >> (64 - numBits));
  53. }
  54. /** ZSTD_ldm_getChecksum() :
  55. * numBitsToDiscard should be <= 32
  56. * @return : the next most significant 32 bits after numBitsToDiscard */
  57. static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard)
  58. {
  59. assert(numBitsToDiscard <= 32);
  60. return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF;
  61. }
  62. /** ZSTD_ldm_getTag() ;
  63. * Given the hash, returns the most significant numTagBits bits
  64. * after (32 + hbits) bits.
  65. *
  66. * If there are not enough bits remaining, return the last
  67. * numTagBits bits. */
  68. static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits)
  69. {
  70. assert(numTagBits < 32 && hbits <= 32);
  71. if (32 - hbits < numTagBits) {
  72. return hash & (((U32)1 << numTagBits) - 1);
  73. } else {
  74. return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1);
  75. }
  76. }
  77. /** ZSTD_ldm_getBucket() :
  78. * Returns a pointer to the start of the bucket associated with hash. */
  79. static ldmEntry_t* ZSTD_ldm_getBucket(
  80. ldmState_t* ldmState, size_t hash, ldmParams_t const ldmParams)
  81. {
  82. return ldmState->hashTable + (hash << ldmParams.bucketSizeLog);
  83. }
  84. /** ZSTD_ldm_insertEntry() :
  85. * Insert the entry with corresponding hash into the hash table */
  86. static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
  87. size_t const hash, const ldmEntry_t entry,
  88. ldmParams_t const ldmParams)
  89. {
  90. BYTE* const bucketOffsets = ldmState->bucketOffsets;
  91. *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry;
  92. bucketOffsets[hash]++;
  93. bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1;
  94. }
  95. /** ZSTD_ldm_makeEntryAndInsertByTag() :
  96. *
  97. * Gets the small hash, checksum, and tag from the rollingHash.
  98. *
  99. * If the tag matches (1 << ldmParams.hashEveryLog)-1, then
  100. * creates an ldmEntry from the offset, and inserts it into the hash table.
  101. *
  102. * hBits is the length of the small hash, which is the most significant hBits
  103. * of rollingHash. The checksum is the next 32 most significant bits, followed
  104. * by ldmParams.hashEveryLog bits that make up the tag. */
  105. static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
  106. U64 const rollingHash,
  107. U32 const hBits,
  108. U32 const offset,
  109. ldmParams_t const ldmParams)
  110. {
  111. U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog);
  112. U32 const tagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
  113. if (tag == tagMask) {
  114. U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
  115. U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
  116. ldmEntry_t entry;
  117. entry.offset = offset;
  118. entry.checksum = checksum;
  119. ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams);
  120. }
  121. }
  122. /** ZSTD_ldm_getRollingHash() :
  123. * Get a 64-bit hash using the first len bytes from buf.
  124. *
  125. * Giving bytes s = s_1, s_2, ... s_k, the hash is defined to be
  126. * H(s) = s_1*(a^(k-1)) + s_2*(a^(k-2)) + ... + s_k*(a^0)
  127. *
  128. * where the constant a is defined to be prime8bytes.
  129. *
  130. * The implementation adds an offset to each byte, so
  131. * H(s) = (s_1 + HASH_CHAR_OFFSET)*(a^(k-1)) + ... */
  132. static U64 ZSTD_ldm_getRollingHash(const BYTE* buf, U32 len)
  133. {
  134. U64 ret = 0;
  135. U32 i;
  136. for (i = 0; i < len; i++) {
  137. ret *= prime8bytes;
  138. ret += buf[i] + LDM_HASH_CHAR_OFFSET;
  139. }
  140. return ret;
  141. }
  142. /** ZSTD_ldm_ipow() :
  143. * Return base^exp. */
  144. static U64 ZSTD_ldm_ipow(U64 base, U64 exp)
  145. {
  146. U64 ret = 1;
  147. while (exp) {
  148. if (exp & 1) { ret *= base; }
  149. exp >>= 1;
  150. base *= base;
  151. }
  152. return ret;
  153. }
  154. U64 ZSTD_ldm_getHashPower(U32 minMatchLength) {
  155. assert(minMatchLength >= ZSTD_LDM_MINMATCH_MIN);
  156. return ZSTD_ldm_ipow(prime8bytes, minMatchLength - 1);
  157. }
  158. /** ZSTD_ldm_updateHash() :
  159. * Updates hash by removing toRemove and adding toAdd. */
  160. static U64 ZSTD_ldm_updateHash(U64 hash, BYTE toRemove, BYTE toAdd, U64 hashPower)
  161. {
  162. hash -= ((toRemove + LDM_HASH_CHAR_OFFSET) * hashPower);
  163. hash *= prime8bytes;
  164. hash += toAdd + LDM_HASH_CHAR_OFFSET;
  165. return hash;
  166. }
  167. /** ZSTD_ldm_countBackwardsMatch() :
  168. * Returns the number of bytes that match backwards before pIn and pMatch.
  169. *
  170. * We count only bytes where pMatch >= pBase and pIn >= pAnchor. */
  171. static size_t ZSTD_ldm_countBackwardsMatch(
  172. const BYTE* pIn, const BYTE* pAnchor,
  173. const BYTE* pMatch, const BYTE* pBase)
  174. {
  175. size_t matchLength = 0;
  176. while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) {
  177. pIn--;
  178. pMatch--;
  179. matchLength++;
  180. }
  181. return matchLength;
  182. }
  183. /** ZSTD_ldm_fillFastTables() :
  184. *
  185. * Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.
  186. * This is similar to ZSTD_loadDictionaryContent.
  187. *
  188. * The tables for the other strategies are filled within their
  189. * block compressors. */
  190. static size_t ZSTD_ldm_fillFastTables(ZSTD_CCtx* zc, const void* end)
  191. {
  192. const BYTE* const iend = (const BYTE*)end;
  193. const U32 mls = zc->appliedParams.cParams.searchLength;
  194. switch(zc->appliedParams.cParams.strategy)
  195. {
  196. case ZSTD_fast:
  197. ZSTD_fillHashTable(zc, iend, mls);
  198. zc->nextToUpdate = (U32)(iend - zc->base);
  199. break;
  200. case ZSTD_dfast:
  201. ZSTD_fillDoubleHashTable(zc, iend, mls);
  202. zc->nextToUpdate = (U32)(iend - zc->base);
  203. break;
  204. case ZSTD_greedy:
  205. case ZSTD_lazy:
  206. case ZSTD_lazy2:
  207. case ZSTD_btlazy2:
  208. case ZSTD_btopt:
  209. case ZSTD_btultra:
  210. break;
  211. default:
  212. assert(0); /* not possible : not a valid strategy id */
  213. }
  214. return 0;
  215. }
  216. /** ZSTD_ldm_fillLdmHashTable() :
  217. *
  218. * Fills hashTable from (lastHashed + 1) to iend (non-inclusive).
  219. * lastHash is the rolling hash that corresponds to lastHashed.
  220. *
  221. * Returns the rolling hash corresponding to position iend-1. */
  222. static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
  223. U64 lastHash, const BYTE* lastHashed,
  224. const BYTE* iend, const BYTE* base,
  225. U32 hBits, ldmParams_t const ldmParams)
  226. {
  227. U64 rollingHash = lastHash;
  228. const BYTE* cur = lastHashed + 1;
  229. while (cur < iend) {
  230. rollingHash = ZSTD_ldm_updateHash(rollingHash, cur[-1],
  231. cur[ldmParams.minMatchLength-1],
  232. state->hashPower);
  233. ZSTD_ldm_makeEntryAndInsertByTag(state,
  234. rollingHash, hBits,
  235. (U32)(cur - base), ldmParams);
  236. ++cur;
  237. }
  238. return rollingHash;
  239. }
  240. /** ZSTD_ldm_limitTableUpdate() :
  241. *
  242. * Sets cctx->nextToUpdate to a position corresponding closer to anchor
  243. * if it is far way
  244. * (after a long match, only update tables a limited amount). */
  245. static void ZSTD_ldm_limitTableUpdate(ZSTD_CCtx* cctx, const BYTE* anchor)
  246. {
  247. U32 const current = (U32)(anchor - cctx->base);
  248. if (current > cctx->nextToUpdate + 1024) {
  249. cctx->nextToUpdate =
  250. current - MIN(512, current - cctx->nextToUpdate - 1024);
  251. }
  252. }
  253. typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
  254. /* defined in zstd_compress.c */
  255. ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
  256. FORCE_INLINE_TEMPLATE
  257. size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
  258. const void* src, size_t srcSize)
  259. {
  260. ldmState_t* const ldmState = &(cctx->ldmState);
  261. const ldmParams_t ldmParams = cctx->appliedParams.ldmParams;
  262. const U64 hashPower = ldmState->hashPower;
  263. const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
  264. const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
  265. const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
  266. seqStore_t* const seqStorePtr = &(cctx->seqStore);
  267. const BYTE* const base = cctx->base;
  268. const BYTE* const istart = (const BYTE*)src;
  269. const BYTE* ip = istart;
  270. const BYTE* anchor = istart;
  271. const U32 lowestIndex = cctx->dictLimit;
  272. const BYTE* const lowest = base + lowestIndex;
  273. const BYTE* const iend = istart + srcSize;
  274. const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
  275. const ZSTD_blockCompressor blockCompressor =
  276. ZSTD_selectBlockCompressor(cctx->appliedParams.cParams.strategy, 0);
  277. U32* const repToConfirm = seqStorePtr->repToConfirm;
  278. U32 savedRep[ZSTD_REP_NUM];
  279. U64 rollingHash = 0;
  280. const BYTE* lastHashed = NULL;
  281. size_t i, lastLiterals;
  282. /* Save seqStorePtr->rep and copy repToConfirm */
  283. for (i = 0; i < ZSTD_REP_NUM; i++)
  284. savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
  285. /* Main Search Loop */
  286. while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
  287. size_t mLength;
  288. U32 const current = (U32)(ip - base);
  289. size_t forwardMatchLength = 0, backwardMatchLength = 0;
  290. ldmEntry_t* bestEntry = NULL;
  291. if (ip != istart) {
  292. rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
  293. lastHashed[ldmParams.minMatchLength],
  294. hashPower);
  295. } else {
  296. rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
  297. }
  298. lastHashed = ip;
  299. /* Do not insert and do not look for a match */
  300. if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
  301. ldmTagMask) {
  302. ip++;
  303. continue;
  304. }
  305. /* Get the best entry and compute the match lengths */
  306. {
  307. ldmEntry_t* const bucket =
  308. ZSTD_ldm_getBucket(ldmState,
  309. ZSTD_ldm_getSmallHash(rollingHash, hBits),
  310. ldmParams);
  311. ldmEntry_t* cur;
  312. size_t bestMatchLength = 0;
  313. U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
  314. for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
  315. const BYTE* const pMatch = cur->offset + base;
  316. size_t curForwardMatchLength, curBackwardMatchLength,
  317. curTotalMatchLength;
  318. if (cur->checksum != checksum || cur->offset <= lowestIndex) {
  319. continue;
  320. }
  321. curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
  322. if (curForwardMatchLength < ldmParams.minMatchLength) {
  323. continue;
  324. }
  325. curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
  326. ip, anchor, pMatch, lowest);
  327. curTotalMatchLength = curForwardMatchLength +
  328. curBackwardMatchLength;
  329. if (curTotalMatchLength > bestMatchLength) {
  330. bestMatchLength = curTotalMatchLength;
  331. forwardMatchLength = curForwardMatchLength;
  332. backwardMatchLength = curBackwardMatchLength;
  333. bestEntry = cur;
  334. }
  335. }
  336. }
  337. /* No match found -- continue searching */
  338. if (bestEntry == NULL) {
  339. ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
  340. hBits, current,
  341. ldmParams);
  342. ip++;
  343. continue;
  344. }
  345. /* Match found */
  346. mLength = forwardMatchLength + backwardMatchLength;
  347. ip -= backwardMatchLength;
  348. /* Call the block compressor on the remaining literals */
  349. {
  350. U32 const matchIndex = bestEntry->offset;
  351. const BYTE* const match = base + matchIndex - backwardMatchLength;
  352. U32 const offset = (U32)(ip - match);
  353. /* Overwrite rep codes */
  354. for (i = 0; i < ZSTD_REP_NUM; i++)
  355. seqStorePtr->rep[i] = repToConfirm[i];
  356. /* Fill tables for block compressor */
  357. ZSTD_ldm_limitTableUpdate(cctx, anchor);
  358. ZSTD_ldm_fillFastTables(cctx, anchor);
  359. /* Call block compressor and get remaining literals */
  360. lastLiterals = blockCompressor(cctx, anchor, ip - anchor);
  361. cctx->nextToUpdate = (U32)(ip - base);
  362. /* Update repToConfirm with the new offset */
  363. for (i = ZSTD_REP_NUM - 1; i > 0; i--)
  364. repToConfirm[i] = repToConfirm[i-1];
  365. repToConfirm[0] = offset;
  366. /* Store the sequence with the leftover literals */
  367. ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
  368. offset + ZSTD_REP_MOVE, mLength - MINMATCH);
  369. }
  370. /* Insert the current entry into the hash table */
  371. ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
  372. (U32)(lastHashed - base),
  373. ldmParams);
  374. assert(ip + backwardMatchLength == lastHashed);
  375. /* Fill the hash table from lastHashed+1 to ip+mLength*/
  376. /* Heuristic: don't need to fill the entire table at end of block */
  377. if (ip + mLength < ilimit) {
  378. rollingHash = ZSTD_ldm_fillLdmHashTable(
  379. ldmState, rollingHash, lastHashed,
  380. ip + mLength, base, hBits, ldmParams);
  381. lastHashed = ip + mLength - 1;
  382. }
  383. ip += mLength;
  384. anchor = ip;
  385. /* Check immediate repcode */
  386. while ( (ip < ilimit)
  387. && ( (repToConfirm[1] > 0) && (repToConfirm[1] <= (U32)(ip-lowest))
  388. && (MEM_read32(ip) == MEM_read32(ip - repToConfirm[1])) )) {
  389. size_t const rLength = ZSTD_count(ip+4, ip+4-repToConfirm[1],
  390. iend) + 4;
  391. /* Swap repToConfirm[1] <=> repToConfirm[0] */
  392. {
  393. U32 const tmpOff = repToConfirm[1];
  394. repToConfirm[1] = repToConfirm[0];
  395. repToConfirm[0] = tmpOff;
  396. }
  397. ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
  398. /* Fill the hash table from lastHashed+1 to ip+rLength*/
  399. if (ip + rLength < ilimit) {
  400. rollingHash = ZSTD_ldm_fillLdmHashTable(
  401. ldmState, rollingHash, lastHashed,
  402. ip + rLength, base, hBits, ldmParams);
  403. lastHashed = ip + rLength - 1;
  404. }
  405. ip += rLength;
  406. anchor = ip;
  407. }
  408. }
  409. /* Overwrite rep */
  410. for (i = 0; i < ZSTD_REP_NUM; i++)
  411. seqStorePtr->rep[i] = repToConfirm[i];
  412. ZSTD_ldm_limitTableUpdate(cctx, anchor);
  413. ZSTD_ldm_fillFastTables(cctx, anchor);
  414. lastLiterals = blockCompressor(cctx, anchor, iend - anchor);
  415. cctx->nextToUpdate = (U32)(iend - base);
  416. /* Restore seqStorePtr->rep */
  417. for (i = 0; i < ZSTD_REP_NUM; i++)
  418. seqStorePtr->rep[i] = savedRep[i];
  419. /* Return the last literals size */
  420. return lastLiterals;
  421. }
  422. size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* ctx,
  423. const void* src, size_t srcSize)
  424. {
  425. return ZSTD_compressBlock_ldm_generic(ctx, src, srcSize);
  426. }
  427. static size_t ZSTD_compressBlock_ldm_extDict_generic(
  428. ZSTD_CCtx* ctx,
  429. const void* src, size_t srcSize)
  430. {
  431. ldmState_t* const ldmState = &(ctx->ldmState);
  432. const ldmParams_t ldmParams = ctx->appliedParams.ldmParams;
  433. const U64 hashPower = ldmState->hashPower;
  434. const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
  435. const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
  436. const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
  437. seqStore_t* const seqStorePtr = &(ctx->seqStore);
  438. const BYTE* const base = ctx->base;
  439. const BYTE* const dictBase = ctx->dictBase;
  440. const BYTE* const istart = (const BYTE*)src;
  441. const BYTE* ip = istart;
  442. const BYTE* anchor = istart;
  443. const U32 lowestIndex = ctx->lowLimit;
  444. const BYTE* const dictStart = dictBase + lowestIndex;
  445. const U32 dictLimit = ctx->dictLimit;
  446. const BYTE* const lowPrefixPtr = base + dictLimit;
  447. const BYTE* const dictEnd = dictBase + dictLimit;
  448. const BYTE* const iend = istart + srcSize;
  449. const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
  450. const ZSTD_blockCompressor blockCompressor =
  451. ZSTD_selectBlockCompressor(ctx->appliedParams.cParams.strategy, 1);
  452. U32* const repToConfirm = seqStorePtr->repToConfirm;
  453. U32 savedRep[ZSTD_REP_NUM];
  454. U64 rollingHash = 0;
  455. const BYTE* lastHashed = NULL;
  456. size_t i, lastLiterals;
  457. /* Save seqStorePtr->rep and copy repToConfirm */
  458. for (i = 0; i < ZSTD_REP_NUM; i++) {
  459. savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
  460. }
  461. /* Search Loop */
  462. while (ip < ilimit) { /* < instead of <=, because (ip+1) */
  463. size_t mLength;
  464. const U32 current = (U32)(ip-base);
  465. size_t forwardMatchLength = 0, backwardMatchLength = 0;
  466. ldmEntry_t* bestEntry = NULL;
  467. if (ip != istart) {
  468. rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
  469. lastHashed[ldmParams.minMatchLength],
  470. hashPower);
  471. } else {
  472. rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
  473. }
  474. lastHashed = ip;
  475. if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
  476. ldmTagMask) {
  477. /* Don't insert and don't look for a match */
  478. ip++;
  479. continue;
  480. }
  481. /* Get the best entry and compute the match lengths */
  482. {
  483. ldmEntry_t* const bucket =
  484. ZSTD_ldm_getBucket(ldmState,
  485. ZSTD_ldm_getSmallHash(rollingHash, hBits),
  486. ldmParams);
  487. ldmEntry_t* cur;
  488. size_t bestMatchLength = 0;
  489. U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
  490. for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
  491. const BYTE* const curMatchBase =
  492. cur->offset < dictLimit ? dictBase : base;
  493. const BYTE* const pMatch = curMatchBase + cur->offset;
  494. const BYTE* const matchEnd =
  495. cur->offset < dictLimit ? dictEnd : iend;
  496. const BYTE* const lowMatchPtr =
  497. cur->offset < dictLimit ? dictStart : lowPrefixPtr;
  498. size_t curForwardMatchLength, curBackwardMatchLength,
  499. curTotalMatchLength;
  500. if (cur->checksum != checksum || cur->offset <= lowestIndex) {
  501. continue;
  502. }
  503. curForwardMatchLength = ZSTD_count_2segments(
  504. ip, pMatch, iend,
  505. matchEnd, lowPrefixPtr);
  506. if (curForwardMatchLength < ldmParams.minMatchLength) {
  507. continue;
  508. }
  509. curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
  510. ip, anchor, pMatch, lowMatchPtr);
  511. curTotalMatchLength = curForwardMatchLength +
  512. curBackwardMatchLength;
  513. if (curTotalMatchLength > bestMatchLength) {
  514. bestMatchLength = curTotalMatchLength;
  515. forwardMatchLength = curForwardMatchLength;
  516. backwardMatchLength = curBackwardMatchLength;
  517. bestEntry = cur;
  518. }
  519. }
  520. }
  521. /* No match found -- continue searching */
  522. if (bestEntry == NULL) {
  523. ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
  524. (U32)(lastHashed - base),
  525. ldmParams);
  526. ip++;
  527. continue;
  528. }
  529. /* Match found */
  530. mLength = forwardMatchLength + backwardMatchLength;
  531. ip -= backwardMatchLength;
  532. /* Call the block compressor on the remaining literals */
  533. {
  534. /* ip = current - backwardMatchLength
  535. * The match is at (bestEntry->offset - backwardMatchLength) */
  536. U32 const matchIndex = bestEntry->offset;
  537. U32 const offset = current - matchIndex;
  538. /* Overwrite rep codes */
  539. for (i = 0; i < ZSTD_REP_NUM; i++)
  540. seqStorePtr->rep[i] = repToConfirm[i];
  541. /* Fill the hash table for the block compressor */
  542. ZSTD_ldm_limitTableUpdate(ctx, anchor);
  543. ZSTD_ldm_fillFastTables(ctx, anchor);
  544. /* Call block compressor and get remaining literals */
  545. lastLiterals = blockCompressor(ctx, anchor, ip - anchor);
  546. ctx->nextToUpdate = (U32)(ip - base);
  547. /* Update repToConfirm with the new offset */
  548. for (i = ZSTD_REP_NUM - 1; i > 0; i--)
  549. repToConfirm[i] = repToConfirm[i-1];
  550. repToConfirm[0] = offset;
  551. /* Store the sequence with the leftover literals */
  552. ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
  553. offset + ZSTD_REP_MOVE, mLength - MINMATCH);
  554. }
  555. /* Insert the current entry into the hash table */
  556. ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
  557. (U32)(lastHashed - base),
  558. ldmParams);
  559. /* Fill the hash table from lastHashed+1 to ip+mLength */
  560. assert(ip + backwardMatchLength == lastHashed);
  561. if (ip + mLength < ilimit) {
  562. rollingHash = ZSTD_ldm_fillLdmHashTable(
  563. ldmState, rollingHash, lastHashed,
  564. ip + mLength, base, hBits,
  565. ldmParams);
  566. lastHashed = ip + mLength - 1;
  567. }
  568. ip += mLength;
  569. anchor = ip;
  570. /* check immediate repcode */
  571. while (ip < ilimit) {
  572. U32 const current2 = (U32)(ip-base);
  573. U32 const repIndex2 = current2 - repToConfirm[1];
  574. const BYTE* repMatch2 = repIndex2 < dictLimit ?
  575. dictBase + repIndex2 : base + repIndex2;
  576. if ( (((U32)((dictLimit-1) - repIndex2) >= 3) &
  577. (repIndex2 > lowestIndex)) /* intentional overflow */
  578. && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
  579. const BYTE* const repEnd2 = repIndex2 < dictLimit ?
  580. dictEnd : iend;
  581. size_t const repLength2 =
  582. ZSTD_count_2segments(ip+4, repMatch2+4, iend,
  583. repEnd2, lowPrefixPtr) + 4;
  584. U32 tmpOffset = repToConfirm[1];
  585. repToConfirm[1] = repToConfirm[0];
  586. repToConfirm[0] = tmpOffset;
  587. ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
  588. /* Fill the hash table from lastHashed+1 to ip+repLength2*/
  589. if (ip + repLength2 < ilimit) {
  590. rollingHash = ZSTD_ldm_fillLdmHashTable(
  591. ldmState, rollingHash, lastHashed,
  592. ip + repLength2, base, hBits,
  593. ldmParams);
  594. lastHashed = ip + repLength2 - 1;
  595. }
  596. ip += repLength2;
  597. anchor = ip;
  598. continue;
  599. }
  600. break;
  601. }
  602. }
  603. /* Overwrite rep */
  604. for (i = 0; i < ZSTD_REP_NUM; i++)
  605. seqStorePtr->rep[i] = repToConfirm[i];
  606. ZSTD_ldm_limitTableUpdate(ctx, anchor);
  607. ZSTD_ldm_fillFastTables(ctx, anchor);
  608. /* Call the block compressor one last time on the last literals */
  609. lastLiterals = blockCompressor(ctx, anchor, iend - anchor);
  610. ctx->nextToUpdate = (U32)(iend - base);
  611. /* Restore seqStorePtr->rep */
  612. for (i = 0; i < ZSTD_REP_NUM; i++)
  613. seqStorePtr->rep[i] = savedRep[i];
  614. /* Return the last literals size */
  615. return lastLiterals;
  616. }
  617. size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
  618. const void* src, size_t srcSize)
  619. {
  620. return ZSTD_compressBlock_ldm_extDict_generic(ctx, src, srcSize);
  621. }