LzFind.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /* LzFind.c -- Match finder for LZ algorithms
  2. 2008-10-04 : Igor Pavlov : Public domain */
  3. #include <string.h>
  4. #include "LzFind.h"
  5. #include "LzHash.h"
  6. #define kEmptyHashValue 0
  7. #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
  8. #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
  9. #define kNormalizeMask (~(kNormalizeStepMin - 1))
  10. #define kMaxHistorySize ((UInt32)3 << 30)
  11. #define kStartMaxLen 3
  12. static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
  13. {
  14. if (!p->directInput)
  15. {
  16. alloc->Free(alloc, p->bufferBase);
  17. p->bufferBase = 0;
  18. }
  19. }
  20. /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
  21. static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
  22. {
  23. UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
  24. if (p->directInput)
  25. {
  26. p->blockSize = blockSize;
  27. return 1;
  28. }
  29. if (p->bufferBase == 0 || p->blockSize != blockSize)
  30. {
  31. LzInWindow_Free(p, alloc);
  32. p->blockSize = blockSize;
  33. p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
  34. }
  35. return (p->bufferBase != 0);
  36. }
  37. Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
  38. Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
  39. UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
  40. void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
  41. {
  42. p->posLimit -= subValue;
  43. p->pos -= subValue;
  44. p->streamPos -= subValue;
  45. }
  46. static void MatchFinder_ReadBlock(CMatchFinder *p)
  47. {
  48. if (p->streamEndWasReached || p->result != SZ_OK)
  49. return;
  50. for (;;)
  51. {
  52. Byte *dest = p->buffer + (p->streamPos - p->pos);
  53. size_t size = (p->bufferBase + p->blockSize - dest);
  54. if (size == 0)
  55. return;
  56. p->result = p->stream->Read(p->stream, dest, &size);
  57. if (p->result != SZ_OK)
  58. return;
  59. if (size == 0)
  60. {
  61. p->streamEndWasReached = 1;
  62. return;
  63. }
  64. p->streamPos += (UInt32)size;
  65. if (p->streamPos - p->pos > p->keepSizeAfter)
  66. return;
  67. }
  68. }
  69. void MatchFinder_MoveBlock(CMatchFinder *p)
  70. {
  71. memmove(p->bufferBase,
  72. p->buffer - p->keepSizeBefore,
  73. (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
  74. p->buffer = p->bufferBase + p->keepSizeBefore;
  75. }
  76. int MatchFinder_NeedMove(CMatchFinder *p)
  77. {
  78. /* if (p->streamEndWasReached) return 0; */
  79. return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
  80. }
  81. void MatchFinder_ReadIfRequired(CMatchFinder *p)
  82. {
  83. if (p->streamEndWasReached)
  84. return;
  85. if (p->keepSizeAfter >= p->streamPos - p->pos)
  86. MatchFinder_ReadBlock(p);
  87. }
  88. static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
  89. {
  90. if (MatchFinder_NeedMove(p))
  91. MatchFinder_MoveBlock(p);
  92. MatchFinder_ReadBlock(p);
  93. }
  94. static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
  95. {
  96. p->cutValue = 32;
  97. p->btMode = 1;
  98. p->numHashBytes = 4;
  99. /* p->skipModeBits = 0; */
  100. p->directInput = 0;
  101. p->bigHash = 0;
  102. }
  103. #define kCrcPoly 0xEDB88320
  104. void MatchFinder_Construct(CMatchFinder *p)
  105. {
  106. UInt32 i;
  107. p->bufferBase = 0;
  108. p->directInput = 0;
  109. p->hash = 0;
  110. MatchFinder_SetDefaultSettings(p);
  111. for (i = 0; i < 256; i++)
  112. {
  113. UInt32 r = i;
  114. int j;
  115. for (j = 0; j < 8; j++)
  116. r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
  117. p->crc[i] = r;
  118. }
  119. }
  120. static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
  121. {
  122. alloc->Free(alloc, p->hash);
  123. p->hash = 0;
  124. }
  125. void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
  126. {
  127. MatchFinder_FreeThisClassMemory(p, alloc);
  128. LzInWindow_Free(p, alloc);
  129. }
  130. static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
  131. {
  132. size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
  133. if (sizeInBytes / sizeof(CLzRef) != num)
  134. return 0;
  135. return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
  136. }
  137. int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
  138. UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
  139. ISzAlloc *alloc)
  140. {
  141. UInt32 sizeReserv;
  142. if (historySize > kMaxHistorySize)
  143. {
  144. MatchFinder_Free(p, alloc);
  145. return 0;
  146. }
  147. sizeReserv = historySize >> 1;
  148. if (historySize > ((UInt32)2 << 30))
  149. sizeReserv = historySize >> 2;
  150. sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
  151. p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
  152. p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
  153. /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
  154. if (LzInWindow_Create(p, sizeReserv, alloc))
  155. {
  156. UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
  157. UInt32 hs;
  158. p->matchMaxLen = matchMaxLen;
  159. {
  160. p->fixedHashSize = 0;
  161. if (p->numHashBytes == 2)
  162. hs = (1 << 16) - 1;
  163. else
  164. {
  165. hs = historySize - 1;
  166. hs |= (hs >> 1);
  167. hs |= (hs >> 2);
  168. hs |= (hs >> 4);
  169. hs |= (hs >> 8);
  170. hs >>= 1;
  171. /* hs >>= p->skipModeBits; */
  172. hs |= 0xFFFF; /* don't change it! It's required for Deflate */
  173. if (hs > (1 << 24))
  174. {
  175. if (p->numHashBytes == 3)
  176. hs = (1 << 24) - 1;
  177. else
  178. hs >>= 1;
  179. }
  180. }
  181. p->hashMask = hs;
  182. hs++;
  183. if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
  184. if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
  185. if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
  186. hs += p->fixedHashSize;
  187. }
  188. {
  189. UInt32 prevSize = p->hashSizeSum + p->numSons;
  190. UInt32 newSize;
  191. p->historySize = historySize;
  192. p->hashSizeSum = hs;
  193. p->cyclicBufferSize = newCyclicBufferSize;
  194. p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
  195. newSize = p->hashSizeSum + p->numSons;
  196. if (p->hash != 0 && prevSize == newSize)
  197. return 1;
  198. MatchFinder_FreeThisClassMemory(p, alloc);
  199. p->hash = AllocRefs(newSize, alloc);
  200. if (p->hash != 0)
  201. {
  202. p->son = p->hash + p->hashSizeSum;
  203. return 1;
  204. }
  205. }
  206. }
  207. MatchFinder_Free(p, alloc);
  208. return 0;
  209. }
  210. static void MatchFinder_SetLimits(CMatchFinder *p)
  211. {
  212. UInt32 limit = kMaxValForNormalize - p->pos;
  213. UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
  214. if (limit2 < limit)
  215. limit = limit2;
  216. limit2 = p->streamPos - p->pos;
  217. if (limit2 <= p->keepSizeAfter)
  218. {
  219. if (limit2 > 0)
  220. limit2 = 1;
  221. }
  222. else
  223. limit2 -= p->keepSizeAfter;
  224. if (limit2 < limit)
  225. limit = limit2;
  226. {
  227. UInt32 lenLimit = p->streamPos - p->pos;
  228. if (lenLimit > p->matchMaxLen)
  229. lenLimit = p->matchMaxLen;
  230. p->lenLimit = lenLimit;
  231. }
  232. p->posLimit = p->pos + limit;
  233. }
  234. void MatchFinder_Init(CMatchFinder *p)
  235. {
  236. UInt32 i;
  237. for (i = 0; i < p->hashSizeSum; i++)
  238. p->hash[i] = kEmptyHashValue;
  239. p->cyclicBufferPos = 0;
  240. p->buffer = p->bufferBase;
  241. p->pos = p->streamPos = p->cyclicBufferSize;
  242. p->result = SZ_OK;
  243. p->streamEndWasReached = 0;
  244. MatchFinder_ReadBlock(p);
  245. MatchFinder_SetLimits(p);
  246. }
  247. static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
  248. {
  249. return (p->pos - p->historySize - 1) & kNormalizeMask;
  250. }
  251. void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
  252. {
  253. UInt32 i;
  254. for (i = 0; i < numItems; i++)
  255. {
  256. UInt32 value = items[i];
  257. if (value <= subValue)
  258. value = kEmptyHashValue;
  259. else
  260. value -= subValue;
  261. items[i] = value;
  262. }
  263. }
  264. static void MatchFinder_Normalize(CMatchFinder *p)
  265. {
  266. UInt32 subValue = MatchFinder_GetSubValue(p);
  267. MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
  268. MatchFinder_ReduceOffsets(p, subValue);
  269. }
  270. static void MatchFinder_CheckLimits(CMatchFinder *p)
  271. {
  272. if (p->pos == kMaxValForNormalize)
  273. MatchFinder_Normalize(p);
  274. if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
  275. MatchFinder_CheckAndMoveAndRead(p);
  276. if (p->cyclicBufferPos == p->cyclicBufferSize)
  277. p->cyclicBufferPos = 0;
  278. MatchFinder_SetLimits(p);
  279. }
  280. static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  281. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  282. UInt32 *distances, UInt32 maxLen)
  283. {
  284. son[_cyclicBufferPos] = curMatch;
  285. for (;;)
  286. {
  287. UInt32 delta = pos - curMatch;
  288. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  289. return distances;
  290. {
  291. const Byte *pb = cur - delta;
  292. curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
  293. if (pb[maxLen] == cur[maxLen] && *pb == *cur)
  294. {
  295. UInt32 len = 0;
  296. while (++len != lenLimit)
  297. if (pb[len] != cur[len])
  298. break;
  299. if (maxLen < len)
  300. {
  301. *distances++ = maxLen = len;
  302. *distances++ = delta - 1;
  303. if (len == lenLimit)
  304. return distances;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  311. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  312. UInt32 *distances, UInt32 maxLen)
  313. {
  314. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  315. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  316. UInt32 len0 = 0, len1 = 0;
  317. for (;;)
  318. {
  319. UInt32 delta = pos - curMatch;
  320. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  321. {
  322. *ptr0 = *ptr1 = kEmptyHashValue;
  323. return distances;
  324. }
  325. {
  326. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  327. const Byte *pb = cur - delta;
  328. UInt32 len = (len0 < len1 ? len0 : len1);
  329. if (pb[len] == cur[len])
  330. {
  331. if (++len != lenLimit && pb[len] == cur[len])
  332. while (++len != lenLimit)
  333. if (pb[len] != cur[len])
  334. break;
  335. if (maxLen < len)
  336. {
  337. *distances++ = maxLen = len;
  338. *distances++ = delta - 1;
  339. if (len == lenLimit)
  340. {
  341. *ptr1 = pair[0];
  342. *ptr0 = pair[1];
  343. return distances;
  344. }
  345. }
  346. }
  347. if (pb[len] < cur[len])
  348. {
  349. *ptr1 = curMatch;
  350. ptr1 = pair + 1;
  351. curMatch = *ptr1;
  352. len1 = len;
  353. }
  354. else
  355. {
  356. *ptr0 = curMatch;
  357. ptr0 = pair;
  358. curMatch = *ptr0;
  359. len0 = len;
  360. }
  361. }
  362. }
  363. }
  364. static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  365. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
  366. {
  367. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  368. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  369. UInt32 len0 = 0, len1 = 0;
  370. for (;;)
  371. {
  372. UInt32 delta = pos - curMatch;
  373. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  374. {
  375. *ptr0 = *ptr1 = kEmptyHashValue;
  376. return;
  377. }
  378. {
  379. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  380. const Byte *pb = cur - delta;
  381. UInt32 len = (len0 < len1 ? len0 : len1);
  382. if (pb[len] == cur[len])
  383. {
  384. while (++len != lenLimit)
  385. if (pb[len] != cur[len])
  386. break;
  387. {
  388. if (len == lenLimit)
  389. {
  390. *ptr1 = pair[0];
  391. *ptr0 = pair[1];
  392. return;
  393. }
  394. }
  395. }
  396. if (pb[len] < cur[len])
  397. {
  398. *ptr1 = curMatch;
  399. ptr1 = pair + 1;
  400. curMatch = *ptr1;
  401. len1 = len;
  402. }
  403. else
  404. {
  405. *ptr0 = curMatch;
  406. ptr0 = pair;
  407. curMatch = *ptr0;
  408. len0 = len;
  409. }
  410. }
  411. }
  412. }
  413. #define MOVE_POS \
  414. ++p->cyclicBufferPos; \
  415. p->buffer++; \
  416. if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
  417. #define MOVE_POS_RET MOVE_POS return offset;
  418. static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
  419. #define GET_MATCHES_HEADER2(minLen, ret_op) \
  420. UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
  421. lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
  422. cur = p->buffer;
  423. #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
  424. #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
  425. #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
  426. #define GET_MATCHES_FOOTER(offset, maxLen) \
  427. offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
  428. distances + offset, maxLen) - distances); MOVE_POS_RET;
  429. #define SKIP_FOOTER \
  430. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
  431. static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  432. {
  433. UInt32 offset;
  434. GET_MATCHES_HEADER(2)
  435. HASH2_CALC;
  436. curMatch = p->hash[hashValue];
  437. p->hash[hashValue] = p->pos;
  438. offset = 0;
  439. GET_MATCHES_FOOTER(offset, 1)
  440. }
  441. UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  442. {
  443. UInt32 offset;
  444. GET_MATCHES_HEADER(3)
  445. HASH_ZIP_CALC;
  446. curMatch = p->hash[hashValue];
  447. p->hash[hashValue] = p->pos;
  448. offset = 0;
  449. GET_MATCHES_FOOTER(offset, 2)
  450. }
  451. static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  452. {
  453. UInt32 hash2Value, delta2, maxLen, offset;
  454. GET_MATCHES_HEADER(3)
  455. HASH3_CALC;
  456. delta2 = p->pos - p->hash[hash2Value];
  457. curMatch = p->hash[kFix3HashSize + hashValue];
  458. p->hash[hash2Value] =
  459. p->hash[kFix3HashSize + hashValue] = p->pos;
  460. maxLen = 2;
  461. offset = 0;
  462. if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  463. {
  464. for (; maxLen != lenLimit; maxLen++)
  465. if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  466. break;
  467. distances[0] = maxLen;
  468. distances[1] = delta2 - 1;
  469. offset = 2;
  470. if (maxLen == lenLimit)
  471. {
  472. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  473. MOVE_POS_RET;
  474. }
  475. }
  476. GET_MATCHES_FOOTER(offset, maxLen)
  477. }
  478. static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  479. {
  480. UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
  481. GET_MATCHES_HEADER(4)
  482. HASH4_CALC;
  483. delta2 = p->pos - p->hash[ hash2Value];
  484. delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
  485. curMatch = p->hash[kFix4HashSize + hashValue];
  486. p->hash[ hash2Value] =
  487. p->hash[kFix3HashSize + hash3Value] =
  488. p->hash[kFix4HashSize + hashValue] = p->pos;
  489. maxLen = 1;
  490. offset = 0;
  491. if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  492. {
  493. distances[0] = maxLen = 2;
  494. distances[1] = delta2 - 1;
  495. offset = 2;
  496. }
  497. if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
  498. {
  499. maxLen = 3;
  500. distances[offset + 1] = delta3 - 1;
  501. offset += 2;
  502. delta2 = delta3;
  503. }
  504. if (offset != 0)
  505. {
  506. for (; maxLen != lenLimit; maxLen++)
  507. if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  508. break;
  509. distances[offset - 2] = maxLen;
  510. if (maxLen == lenLimit)
  511. {
  512. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  513. MOVE_POS_RET;
  514. }
  515. }
  516. if (maxLen < 3)
  517. maxLen = 3;
  518. GET_MATCHES_FOOTER(offset, maxLen)
  519. }
  520. static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  521. {
  522. UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
  523. GET_MATCHES_HEADER(4)
  524. HASH4_CALC;
  525. delta2 = p->pos - p->hash[ hash2Value];
  526. delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
  527. curMatch = p->hash[kFix4HashSize + hashValue];
  528. p->hash[ hash2Value] =
  529. p->hash[kFix3HashSize + hash3Value] =
  530. p->hash[kFix4HashSize + hashValue] = p->pos;
  531. maxLen = 1;
  532. offset = 0;
  533. if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  534. {
  535. distances[0] = maxLen = 2;
  536. distances[1] = delta2 - 1;
  537. offset = 2;
  538. }
  539. if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
  540. {
  541. maxLen = 3;
  542. distances[offset + 1] = delta3 - 1;
  543. offset += 2;
  544. delta2 = delta3;
  545. }
  546. if (offset != 0)
  547. {
  548. for (; maxLen != lenLimit; maxLen++)
  549. if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  550. break;
  551. distances[offset - 2] = maxLen;
  552. if (maxLen == lenLimit)
  553. {
  554. p->son[p->cyclicBufferPos] = curMatch;
  555. MOVE_POS_RET;
  556. }
  557. }
  558. if (maxLen < 3)
  559. maxLen = 3;
  560. offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  561. distances + offset, maxLen) - (distances));
  562. MOVE_POS_RET
  563. }
  564. UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  565. {
  566. UInt32 offset;
  567. GET_MATCHES_HEADER(3)
  568. HASH_ZIP_CALC;
  569. curMatch = p->hash[hashValue];
  570. p->hash[hashValue] = p->pos;
  571. offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  572. distances, 2) - (distances));
  573. MOVE_POS_RET
  574. }
  575. static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  576. {
  577. do
  578. {
  579. SKIP_HEADER(2)
  580. HASH2_CALC;
  581. curMatch = p->hash[hashValue];
  582. p->hash[hashValue] = p->pos;
  583. SKIP_FOOTER
  584. }
  585. while (--num != 0);
  586. }
  587. void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  588. {
  589. do
  590. {
  591. SKIP_HEADER(3)
  592. HASH_ZIP_CALC;
  593. curMatch = p->hash[hashValue];
  594. p->hash[hashValue] = p->pos;
  595. SKIP_FOOTER
  596. }
  597. while (--num != 0);
  598. }
  599. static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  600. {
  601. do
  602. {
  603. UInt32 hash2Value;
  604. SKIP_HEADER(3)
  605. HASH3_CALC;
  606. curMatch = p->hash[kFix3HashSize + hashValue];
  607. p->hash[hash2Value] =
  608. p->hash[kFix3HashSize + hashValue] = p->pos;
  609. SKIP_FOOTER
  610. }
  611. while (--num != 0);
  612. }
  613. static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  614. {
  615. do
  616. {
  617. UInt32 hash2Value, hash3Value;
  618. SKIP_HEADER(4)
  619. HASH4_CALC;
  620. curMatch = p->hash[kFix4HashSize + hashValue];
  621. p->hash[ hash2Value] =
  622. p->hash[kFix3HashSize + hash3Value] = p->pos;
  623. p->hash[kFix4HashSize + hashValue] = p->pos;
  624. SKIP_FOOTER
  625. }
  626. while (--num != 0);
  627. }
  628. static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  629. {
  630. do
  631. {
  632. UInt32 hash2Value, hash3Value;
  633. SKIP_HEADER(4)
  634. HASH4_CALC;
  635. curMatch = p->hash[kFix4HashSize + hashValue];
  636. p->hash[ hash2Value] =
  637. p->hash[kFix3HashSize + hash3Value] =
  638. p->hash[kFix4HashSize + hashValue] = p->pos;
  639. p->son[p->cyclicBufferPos] = curMatch;
  640. MOVE_POS
  641. }
  642. while (--num != 0);
  643. }
  644. void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  645. {
  646. do
  647. {
  648. SKIP_HEADER(3)
  649. HASH_ZIP_CALC;
  650. curMatch = p->hash[hashValue];
  651. p->hash[hashValue] = p->pos;
  652. p->son[p->cyclicBufferPos] = curMatch;
  653. MOVE_POS
  654. }
  655. while (--num != 0);
  656. }
  657. void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
  658. {
  659. vTable->Init = (Mf_Init_Func)MatchFinder_Init;
  660. vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
  661. vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
  662. vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
  663. if (!p->btMode)
  664. {
  665. vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
  666. vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
  667. }
  668. else if (p->numHashBytes == 2)
  669. {
  670. vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
  671. vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
  672. }
  673. else if (p->numHashBytes == 3)
  674. {
  675. vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
  676. vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
  677. }
  678. else
  679. {
  680. vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
  681. vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
  682. }
  683. }