lz_encoder_mf.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. // SPDX-License-Identifier: 0BSD
  2. ///////////////////////////////////////////////////////////////////////////////
  3. //
  4. /// \file lz_encoder_mf.c
  5. /// \brief Match finders
  6. ///
  7. // Authors: Igor Pavlov
  8. // Lasse Collin
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "lz_encoder.h"
  12. #include "lz_encoder_hash.h"
  13. #include "memcmplen.h"
  14. /// \brief Find matches starting from the current byte
  15. ///
  16. /// \return The length of the longest match found
  17. extern uint32_t
  18. lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
  19. {
  20. // Call the match finder. It returns the number of length-distance
  21. // pairs found.
  22. // FIXME: Minimum count is zero, what _exactly_ is the maximum?
  23. const uint32_t count = mf->find(mf, matches);
  24. // Length of the longest match; assume that no matches were found
  25. // and thus the maximum length is zero.
  26. uint32_t len_best = 0;
  27. if (count > 0) {
  28. #ifndef NDEBUG
  29. // Validate the matches.
  30. for (uint32_t i = 0; i < count; ++i) {
  31. assert(matches[i].len <= mf->nice_len);
  32. assert(matches[i].dist < mf->read_pos);
  33. assert(memcmp(mf_ptr(mf) - 1,
  34. mf_ptr(mf) - matches[i].dist - 2,
  35. matches[i].len) == 0);
  36. }
  37. #endif
  38. // The last used element in the array contains
  39. // the longest match.
  40. len_best = matches[count - 1].len;
  41. // If a match of maximum search length was found, try to
  42. // extend the match to maximum possible length.
  43. if (len_best == mf->nice_len) {
  44. // The limit for the match length is either the
  45. // maximum match length supported by the LZ-based
  46. // encoder or the number of bytes left in the
  47. // dictionary, whichever is smaller.
  48. uint32_t limit = mf_avail(mf) + 1;
  49. if (limit > mf->match_len_max)
  50. limit = mf->match_len_max;
  51. // Pointer to the byte we just ran through
  52. // the match finder.
  53. const uint8_t *p1 = mf_ptr(mf) - 1;
  54. // Pointer to the beginning of the match. We need -1
  55. // here because the match distances are zero based.
  56. const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
  57. len_best = lzma_memcmplen(p1, p2, len_best, limit);
  58. }
  59. }
  60. *count_ptr = count;
  61. // Finally update the read position to indicate that match finder was
  62. // run for this dictionary offset.
  63. ++mf->read_ahead;
  64. return len_best;
  65. }
  66. /// Hash value to indicate unused element in the hash. Since we start the
  67. /// positions from dict_size + 1, zero is always too far to qualify
  68. /// as usable match position.
  69. #define EMPTY_HASH_VALUE 0
  70. /// Normalization must be done when lzma_mf.offset + lzma_mf.read_pos
  71. /// reaches MUST_NORMALIZE_POS.
  72. #define MUST_NORMALIZE_POS UINT32_MAX
  73. /// \brief Normalizes hash values
  74. ///
  75. /// The hash arrays store positions of match candidates. The positions are
  76. /// relative to an arbitrary offset that is not the same as the absolute
  77. /// offset in the input stream. The relative position of the current byte
  78. /// is lzma_mf.offset + lzma_mf.read_pos. The distances of the matches are
  79. /// the differences of the current read position and the position found from
  80. /// the hash.
  81. ///
  82. /// To prevent integer overflows of the offsets stored in the hash arrays,
  83. /// we need to "normalize" the stored values now and then. During the
  84. /// normalization, we drop values that indicate distance greater than the
  85. /// dictionary size, thus making space for new values.
  86. static void
  87. normalize(lzma_mf *mf)
  88. {
  89. assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
  90. // In future we may not want to touch the lowest bits, because there
  91. // may be match finders that use larger resolution than one byte.
  92. const uint32_t subvalue
  93. = (MUST_NORMALIZE_POS - mf->cyclic_size);
  94. // & ~((UINT32_C(1) << 10) - 1);
  95. for (uint32_t i = 0; i < mf->hash_count; ++i) {
  96. // If the distance is greater than the dictionary size,
  97. // we can simply mark the hash element as empty.
  98. if (mf->hash[i] <= subvalue)
  99. mf->hash[i] = EMPTY_HASH_VALUE;
  100. else
  101. mf->hash[i] -= subvalue;
  102. }
  103. for (uint32_t i = 0; i < mf->sons_count; ++i) {
  104. // Do the same for mf->son.
  105. //
  106. // NOTE: There may be uninitialized elements in mf->son.
  107. // Valgrind may complain that the "if" below depends on
  108. // an uninitialized value. In this case it is safe to ignore
  109. // the warning. See also the comments in lz_encoder_init()
  110. // in lz_encoder.c.
  111. if (mf->son[i] <= subvalue)
  112. mf->son[i] = EMPTY_HASH_VALUE;
  113. else
  114. mf->son[i] -= subvalue;
  115. }
  116. // Update offset to match the new locations.
  117. mf->offset -= subvalue;
  118. return;
  119. }
  120. /// Mark the current byte as processed from point of view of the match finder.
  121. static void
  122. move_pos(lzma_mf *mf)
  123. {
  124. if (++mf->cyclic_pos == mf->cyclic_size)
  125. mf->cyclic_pos = 0;
  126. ++mf->read_pos;
  127. assert(mf->read_pos <= mf->write_pos);
  128. if (unlikely(mf->read_pos + mf->offset == UINT32_MAX))
  129. normalize(mf);
  130. }
  131. /// When flushing, we cannot run the match finder unless there is nice_len
  132. /// bytes available in the dictionary. Instead, we skip running the match
  133. /// finder (indicating that no match was found), and count how many bytes we
  134. /// have ignored this way.
  135. ///
  136. /// When new data is given after the flushing was completed, the match finder
  137. /// is restarted by rewinding mf->read_pos backwards by mf->pending. Then
  138. /// the missed bytes are added to the hash using the match finder's skip
  139. /// function (with small amount of input, it may start using mf->pending
  140. /// again if flushing).
  141. ///
  142. /// Due to this rewinding, we don't touch cyclic_pos or test for
  143. /// normalization. It will be done when the match finder's skip function
  144. /// catches up after a flush.
  145. static void
  146. move_pending(lzma_mf *mf)
  147. {
  148. ++mf->read_pos;
  149. assert(mf->read_pos <= mf->write_pos);
  150. ++mf->pending;
  151. }
  152. /// Calculate len_limit and determine if there is enough input to run
  153. /// the actual match finder code. Sets up "cur" and "pos". This macro
  154. /// is used by all find functions and binary tree skip functions. Hash
  155. /// chain skip function doesn't need len_limit so a simpler code is used
  156. /// in them.
  157. #define header(is_bt, len_min, ret_op) \
  158. uint32_t len_limit = mf_avail(mf); \
  159. if (mf->nice_len <= len_limit) { \
  160. len_limit = mf->nice_len; \
  161. } else if (len_limit < (len_min) \
  162. || (is_bt && mf->action == LZMA_SYNC_FLUSH)) { \
  163. assert(mf->action != LZMA_RUN); \
  164. move_pending(mf); \
  165. ret_op; \
  166. } \
  167. const uint8_t *cur = mf_ptr(mf); \
  168. const uint32_t pos = mf->read_pos + mf->offset
  169. /// Header for find functions. "return 0" indicates that zero matches
  170. /// were found.
  171. #define header_find(is_bt, len_min) \
  172. header(is_bt, len_min, return 0); \
  173. uint32_t matches_count = 0
  174. /// Header for a loop in a skip function. "continue" tells to skip the rest
  175. /// of the code in the loop.
  176. #define header_skip(is_bt, len_min) \
  177. header(is_bt, len_min, continue)
  178. /// Calls hc_find_func() or bt_find_func() and calculates the total number
  179. /// of matches found. Updates the dictionary position and returns the number
  180. /// of matches found.
  181. #define call_find(func, len_best) \
  182. do { \
  183. matches_count = (uint32_t)(func(len_limit, pos, cur, cur_match, \
  184. mf->depth, mf->son, \
  185. mf->cyclic_pos, mf->cyclic_size, \
  186. matches + matches_count, len_best) \
  187. - matches); \
  188. move_pos(mf); \
  189. return matches_count; \
  190. } while (0)
  191. ////////////////
  192. // Hash Chain //
  193. ////////////////
  194. #if defined(HAVE_MF_HC3) || defined(HAVE_MF_HC4)
  195. ///
  196. ///
  197. /// \param len_limit Don't look for matches longer than len_limit.
  198. /// \param pos lzma_mf.read_pos + lzma_mf.offset
  199. /// \param cur Pointer to current byte (mf_ptr(mf))
  200. /// \param cur_match Start position of the current match candidate
  201. /// \param depth Maximum length of the hash chain
  202. /// \param son lzma_mf.son (contains the hash chain)
  203. /// \param cyclic_pos lzma_mf.cyclic_pos
  204. /// \param cyclic_size lzma_mf_cyclic_size
  205. /// \param matches Array to hold the matches.
  206. /// \param len_best The length of the longest match found so far.
  207. static lzma_match *
  208. hc_find_func(
  209. const uint32_t len_limit,
  210. const uint32_t pos,
  211. const uint8_t *const cur,
  212. uint32_t cur_match,
  213. uint32_t depth,
  214. uint32_t *const son,
  215. const uint32_t cyclic_pos,
  216. const uint32_t cyclic_size,
  217. lzma_match *matches,
  218. uint32_t len_best)
  219. {
  220. son[cyclic_pos] = cur_match;
  221. while (true) {
  222. const uint32_t delta = pos - cur_match;
  223. if (depth-- == 0 || delta >= cyclic_size)
  224. return matches;
  225. const uint8_t *const pb = cur - delta;
  226. cur_match = son[cyclic_pos - delta
  227. + (delta > cyclic_pos ? cyclic_size : 0)];
  228. if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
  229. uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
  230. if (len_best < len) {
  231. len_best = len;
  232. matches->len = len;
  233. matches->dist = delta - 1;
  234. ++matches;
  235. if (len == len_limit)
  236. return matches;
  237. }
  238. }
  239. }
  240. }
  241. #define hc_find(len_best) \
  242. call_find(hc_find_func, len_best)
  243. #define hc_skip() \
  244. do { \
  245. mf->son[mf->cyclic_pos] = cur_match; \
  246. move_pos(mf); \
  247. } while (0)
  248. #endif
  249. #ifdef HAVE_MF_HC3
  250. extern uint32_t
  251. lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
  252. {
  253. header_find(false, 3);
  254. hash_3_calc();
  255. const uint32_t delta2 = pos - mf->hash[hash_2_value];
  256. const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
  257. mf->hash[hash_2_value] = pos;
  258. mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
  259. uint32_t len_best = 2;
  260. if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
  261. len_best = lzma_memcmplen(cur - delta2, cur,
  262. len_best, len_limit);
  263. matches[0].len = len_best;
  264. matches[0].dist = delta2 - 1;
  265. matches_count = 1;
  266. if (len_best == len_limit) {
  267. hc_skip();
  268. return 1; // matches_count
  269. }
  270. }
  271. hc_find(len_best);
  272. }
  273. extern void
  274. lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
  275. {
  276. do {
  277. if (mf_avail(mf) < 3) {
  278. move_pending(mf);
  279. continue;
  280. }
  281. const uint8_t *cur = mf_ptr(mf);
  282. const uint32_t pos = mf->read_pos + mf->offset;
  283. hash_3_calc();
  284. const uint32_t cur_match
  285. = mf->hash[FIX_3_HASH_SIZE + hash_value];
  286. mf->hash[hash_2_value] = pos;
  287. mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
  288. hc_skip();
  289. } while (--amount != 0);
  290. }
  291. #endif
  292. #ifdef HAVE_MF_HC4
  293. extern uint32_t
  294. lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
  295. {
  296. header_find(false, 4);
  297. hash_4_calc();
  298. uint32_t delta2 = pos - mf->hash[hash_2_value];
  299. const uint32_t delta3
  300. = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
  301. const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
  302. mf->hash[hash_2_value ] = pos;
  303. mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
  304. mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
  305. uint32_t len_best = 1;
  306. if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
  307. len_best = 2;
  308. matches[0].len = 2;
  309. matches[0].dist = delta2 - 1;
  310. matches_count = 1;
  311. }
  312. if (delta2 != delta3 && delta3 < mf->cyclic_size
  313. && *(cur - delta3) == *cur) {
  314. len_best = 3;
  315. matches[matches_count++].dist = delta3 - 1;
  316. delta2 = delta3;
  317. }
  318. if (matches_count != 0) {
  319. len_best = lzma_memcmplen(cur - delta2, cur,
  320. len_best, len_limit);
  321. matches[matches_count - 1].len = len_best;
  322. if (len_best == len_limit) {
  323. hc_skip();
  324. return matches_count;
  325. }
  326. }
  327. if (len_best < 3)
  328. len_best = 3;
  329. hc_find(len_best);
  330. }
  331. extern void
  332. lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
  333. {
  334. do {
  335. if (mf_avail(mf) < 4) {
  336. move_pending(mf);
  337. continue;
  338. }
  339. const uint8_t *cur = mf_ptr(mf);
  340. const uint32_t pos = mf->read_pos + mf->offset;
  341. hash_4_calc();
  342. const uint32_t cur_match
  343. = mf->hash[FIX_4_HASH_SIZE + hash_value];
  344. mf->hash[hash_2_value] = pos;
  345. mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
  346. mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
  347. hc_skip();
  348. } while (--amount != 0);
  349. }
  350. #endif
  351. /////////////////
  352. // Binary Tree //
  353. /////////////////
  354. #if defined(HAVE_MF_BT2) || defined(HAVE_MF_BT3) || defined(HAVE_MF_BT4)
  355. static lzma_match *
  356. bt_find_func(
  357. const uint32_t len_limit,
  358. const uint32_t pos,
  359. const uint8_t *const cur,
  360. uint32_t cur_match,
  361. uint32_t depth,
  362. uint32_t *const son,
  363. const uint32_t cyclic_pos,
  364. const uint32_t cyclic_size,
  365. lzma_match *matches,
  366. uint32_t len_best)
  367. {
  368. uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
  369. uint32_t *ptr1 = son + (cyclic_pos << 1);
  370. uint32_t len0 = 0;
  371. uint32_t len1 = 0;
  372. while (true) {
  373. const uint32_t delta = pos - cur_match;
  374. if (depth-- == 0 || delta >= cyclic_size) {
  375. *ptr0 = EMPTY_HASH_VALUE;
  376. *ptr1 = EMPTY_HASH_VALUE;
  377. return matches;
  378. }
  379. uint32_t *const pair = son + ((cyclic_pos - delta
  380. + (delta > cyclic_pos ? cyclic_size : 0))
  381. << 1);
  382. const uint8_t *const pb = cur - delta;
  383. uint32_t len = my_min(len0, len1);
  384. if (pb[len] == cur[len]) {
  385. len = lzma_memcmplen(pb, cur, len + 1, len_limit);
  386. if (len_best < len) {
  387. len_best = len;
  388. matches->len = len;
  389. matches->dist = delta - 1;
  390. ++matches;
  391. if (len == len_limit) {
  392. *ptr1 = pair[0];
  393. *ptr0 = pair[1];
  394. return matches;
  395. }
  396. }
  397. }
  398. if (pb[len] < cur[len]) {
  399. *ptr1 = cur_match;
  400. ptr1 = pair + 1;
  401. cur_match = *ptr1;
  402. len1 = len;
  403. } else {
  404. *ptr0 = cur_match;
  405. ptr0 = pair;
  406. cur_match = *ptr0;
  407. len0 = len;
  408. }
  409. }
  410. }
  411. static void
  412. bt_skip_func(
  413. const uint32_t len_limit,
  414. const uint32_t pos,
  415. const uint8_t *const cur,
  416. uint32_t cur_match,
  417. uint32_t depth,
  418. uint32_t *const son,
  419. const uint32_t cyclic_pos,
  420. const uint32_t cyclic_size)
  421. {
  422. uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
  423. uint32_t *ptr1 = son + (cyclic_pos << 1);
  424. uint32_t len0 = 0;
  425. uint32_t len1 = 0;
  426. while (true) {
  427. const uint32_t delta = pos - cur_match;
  428. if (depth-- == 0 || delta >= cyclic_size) {
  429. *ptr0 = EMPTY_HASH_VALUE;
  430. *ptr1 = EMPTY_HASH_VALUE;
  431. return;
  432. }
  433. uint32_t *pair = son + ((cyclic_pos - delta
  434. + (delta > cyclic_pos ? cyclic_size : 0))
  435. << 1);
  436. const uint8_t *pb = cur - delta;
  437. uint32_t len = my_min(len0, len1);
  438. if (pb[len] == cur[len]) {
  439. len = lzma_memcmplen(pb, cur, len + 1, len_limit);
  440. if (len == len_limit) {
  441. *ptr1 = pair[0];
  442. *ptr0 = pair[1];
  443. return;
  444. }
  445. }
  446. if (pb[len] < cur[len]) {
  447. *ptr1 = cur_match;
  448. ptr1 = pair + 1;
  449. cur_match = *ptr1;
  450. len1 = len;
  451. } else {
  452. *ptr0 = cur_match;
  453. ptr0 = pair;
  454. cur_match = *ptr0;
  455. len0 = len;
  456. }
  457. }
  458. }
  459. #define bt_find(len_best) \
  460. call_find(bt_find_func, len_best)
  461. #define bt_skip() \
  462. do { \
  463. bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, \
  464. mf->son, mf->cyclic_pos, \
  465. mf->cyclic_size); \
  466. move_pos(mf); \
  467. } while (0)
  468. #endif
  469. #ifdef HAVE_MF_BT2
  470. extern uint32_t
  471. lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
  472. {
  473. header_find(true, 2);
  474. hash_2_calc();
  475. const uint32_t cur_match = mf->hash[hash_value];
  476. mf->hash[hash_value] = pos;
  477. bt_find(1);
  478. }
  479. extern void
  480. lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
  481. {
  482. do {
  483. header_skip(true, 2);
  484. hash_2_calc();
  485. const uint32_t cur_match = mf->hash[hash_value];
  486. mf->hash[hash_value] = pos;
  487. bt_skip();
  488. } while (--amount != 0);
  489. }
  490. #endif
  491. #ifdef HAVE_MF_BT3
  492. extern uint32_t
  493. lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
  494. {
  495. header_find(true, 3);
  496. hash_3_calc();
  497. const uint32_t delta2 = pos - mf->hash[hash_2_value];
  498. const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
  499. mf->hash[hash_2_value] = pos;
  500. mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
  501. uint32_t len_best = 2;
  502. if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
  503. len_best = lzma_memcmplen(
  504. cur, cur - delta2, len_best, len_limit);
  505. matches[0].len = len_best;
  506. matches[0].dist = delta2 - 1;
  507. matches_count = 1;
  508. if (len_best == len_limit) {
  509. bt_skip();
  510. return 1; // matches_count
  511. }
  512. }
  513. bt_find(len_best);
  514. }
  515. extern void
  516. lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
  517. {
  518. do {
  519. header_skip(true, 3);
  520. hash_3_calc();
  521. const uint32_t cur_match
  522. = mf->hash[FIX_3_HASH_SIZE + hash_value];
  523. mf->hash[hash_2_value] = pos;
  524. mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
  525. bt_skip();
  526. } while (--amount != 0);
  527. }
  528. #endif
  529. #ifdef HAVE_MF_BT4
  530. extern uint32_t
  531. lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
  532. {
  533. header_find(true, 4);
  534. hash_4_calc();
  535. uint32_t delta2 = pos - mf->hash[hash_2_value];
  536. const uint32_t delta3
  537. = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
  538. const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
  539. mf->hash[hash_2_value] = pos;
  540. mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
  541. mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
  542. uint32_t len_best = 1;
  543. if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
  544. len_best = 2;
  545. matches[0].len = 2;
  546. matches[0].dist = delta2 - 1;
  547. matches_count = 1;
  548. }
  549. if (delta2 != delta3 && delta3 < mf->cyclic_size
  550. && *(cur - delta3) == *cur) {
  551. len_best = 3;
  552. matches[matches_count++].dist = delta3 - 1;
  553. delta2 = delta3;
  554. }
  555. if (matches_count != 0) {
  556. len_best = lzma_memcmplen(
  557. cur, cur - delta2, len_best, len_limit);
  558. matches[matches_count - 1].len = len_best;
  559. if (len_best == len_limit) {
  560. bt_skip();
  561. return matches_count;
  562. }
  563. }
  564. if (len_best < 3)
  565. len_best = 3;
  566. bt_find(len_best);
  567. }
  568. extern void
  569. lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
  570. {
  571. do {
  572. header_skip(true, 4);
  573. hash_4_calc();
  574. const uint32_t cur_match
  575. = mf->hash[FIX_4_HASH_SIZE + hash_value];
  576. mf->hash[hash_2_value] = pos;
  577. mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
  578. mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
  579. bt_skip();
  580. } while (--amount != 0);
  581. }
  582. #endif