LzFind.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. /* LzFind.c -- Match finder for LZ algorithms
  2. 2017-04-03 : Igor Pavlov : Public domain */
  3. #include "Precomp.h"
  4. #include <string.h>
  5. #include "LzFind.h"
  6. #include "LzHash.h"
  7. #define kEmptyHashValue 0
  8. #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
  9. #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
  10. #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
  11. #define kMaxHistorySize ((UInt32)7 << 29)
  12. #define kStartMaxLen 3
  13. static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
  14. {
  15. if (!p->directInput)
  16. {
  17. ISzAlloc_Free(alloc, p->bufferBase);
  18. p->bufferBase = NULL;
  19. }
  20. }
  21. /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
  22. static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
  23. {
  24. UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
  25. if (p->directInput)
  26. {
  27. p->blockSize = blockSize;
  28. return 1;
  29. }
  30. if (!p->bufferBase || p->blockSize != blockSize)
  31. {
  32. LzInWindow_Free(p, alloc);
  33. p->blockSize = blockSize;
  34. p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);
  35. }
  36. return (p->bufferBase != NULL);
  37. }
  38. Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
  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. /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
  51. if (p->directInput)
  52. {
  53. UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
  54. if (curSize > p->directInputRem)
  55. curSize = (UInt32)p->directInputRem;
  56. p->directInputRem -= curSize;
  57. p->streamPos += curSize;
  58. if (p->directInputRem == 0)
  59. p->streamEndWasReached = 1;
  60. return;
  61. }
  62. for (;;)
  63. {
  64. Byte *dest = p->buffer + (p->streamPos - p->pos);
  65. size_t size = (p->bufferBase + p->blockSize - dest);
  66. if (size == 0)
  67. return;
  68. p->result = ISeqInStream_Read(p->stream, dest, &size);
  69. if (p->result != SZ_OK)
  70. return;
  71. if (size == 0)
  72. {
  73. p->streamEndWasReached = 1;
  74. return;
  75. }
  76. p->streamPos += (UInt32)size;
  77. if (p->streamPos - p->pos > p->keepSizeAfter)
  78. return;
  79. }
  80. }
  81. void MatchFinder_MoveBlock(CMatchFinder *p)
  82. {
  83. memmove(p->bufferBase,
  84. p->buffer - p->keepSizeBefore,
  85. (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
  86. p->buffer = p->bufferBase + p->keepSizeBefore;
  87. }
  88. int MatchFinder_NeedMove(CMatchFinder *p)
  89. {
  90. if (p->directInput)
  91. return 0;
  92. /* if (p->streamEndWasReached) return 0; */
  93. return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
  94. }
  95. void MatchFinder_ReadIfRequired(CMatchFinder *p)
  96. {
  97. if (p->streamEndWasReached)
  98. return;
  99. if (p->keepSizeAfter >= p->streamPos - p->pos)
  100. MatchFinder_ReadBlock(p);
  101. }
  102. static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
  103. {
  104. if (MatchFinder_NeedMove(p))
  105. MatchFinder_MoveBlock(p);
  106. MatchFinder_ReadBlock(p);
  107. }
  108. static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
  109. {
  110. p->cutValue = 32;
  111. p->btMode = 1;
  112. p->numHashBytes = 4;
  113. p->bigHash = 0;
  114. }
  115. #define kCrcPoly 0xEDB88320
  116. void MatchFinder_Construct(CMatchFinder *p)
  117. {
  118. UInt32 i;
  119. p->bufferBase = NULL;
  120. p->directInput = 0;
  121. p->hash = NULL;
  122. MatchFinder_SetDefaultSettings(p);
  123. for (i = 0; i < 256; i++)
  124. {
  125. UInt32 r = i;
  126. unsigned j;
  127. for (j = 0; j < 8; j++)
  128. r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
  129. p->crc[i] = r;
  130. }
  131. }
  132. static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
  133. {
  134. ISzAlloc_Free(alloc, p->hash);
  135. p->hash = NULL;
  136. }
  137. void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
  138. {
  139. MatchFinder_FreeThisClassMemory(p, alloc);
  140. LzInWindow_Free(p, alloc);
  141. }
  142. static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
  143. {
  144. size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
  145. if (sizeInBytes / sizeof(CLzRef) != num)
  146. return NULL;
  147. return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);
  148. }
  149. int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
  150. UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
  151. ISzAllocPtr alloc)
  152. {
  153. UInt32 sizeReserv;
  154. if (historySize > kMaxHistorySize)
  155. {
  156. MatchFinder_Free(p, alloc);
  157. return 0;
  158. }
  159. sizeReserv = historySize >> 1;
  160. if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;
  161. else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;
  162. sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
  163. p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
  164. p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
  165. /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
  166. if (LzInWindow_Create(p, sizeReserv, alloc))
  167. {
  168. UInt32 newCyclicBufferSize = historySize + 1;
  169. UInt32 hs;
  170. p->matchMaxLen = matchMaxLen;
  171. {
  172. p->fixedHashSize = 0;
  173. if (p->numHashBytes == 2)
  174. hs = (1 << 16) - 1;
  175. else
  176. {
  177. hs = historySize - 1;
  178. hs |= (hs >> 1);
  179. hs |= (hs >> 2);
  180. hs |= (hs >> 4);
  181. hs |= (hs >> 8);
  182. hs >>= 1;
  183. hs |= 0xFFFF; /* don't change it! It's required for Deflate */
  184. if (hs > (1 << 24))
  185. {
  186. if (p->numHashBytes == 3)
  187. hs = (1 << 24) - 1;
  188. else
  189. hs >>= 1;
  190. /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
  191. }
  192. }
  193. p->hashMask = hs;
  194. hs++;
  195. if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
  196. if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
  197. if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
  198. hs += p->fixedHashSize;
  199. }
  200. {
  201. size_t newSize;
  202. size_t numSons;
  203. p->historySize = historySize;
  204. p->hashSizeSum = hs;
  205. p->cyclicBufferSize = newCyclicBufferSize;
  206. numSons = newCyclicBufferSize;
  207. if (p->btMode)
  208. numSons <<= 1;
  209. newSize = hs + numSons;
  210. if (p->hash && p->numRefs == newSize)
  211. return 1;
  212. MatchFinder_FreeThisClassMemory(p, alloc);
  213. p->numRefs = newSize;
  214. p->hash = AllocRefs(newSize, alloc);
  215. if (p->hash)
  216. {
  217. p->son = p->hash + p->hashSizeSum;
  218. return 1;
  219. }
  220. }
  221. }
  222. MatchFinder_Free(p, alloc);
  223. return 0;
  224. }
  225. static void MatchFinder_SetLimits(CMatchFinder *p)
  226. {
  227. UInt32 limit = kMaxValForNormalize - p->pos;
  228. UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
  229. if (limit2 < limit)
  230. limit = limit2;
  231. limit2 = p->streamPos - p->pos;
  232. if (limit2 <= p->keepSizeAfter)
  233. {
  234. if (limit2 > 0)
  235. limit2 = 1;
  236. }
  237. else
  238. limit2 -= p->keepSizeAfter;
  239. if (limit2 < limit)
  240. limit = limit2;
  241. {
  242. UInt32 lenLimit = p->streamPos - p->pos;
  243. if (lenLimit > p->matchMaxLen)
  244. lenLimit = p->matchMaxLen;
  245. p->lenLimit = lenLimit;
  246. }
  247. p->posLimit = p->pos + limit;
  248. }
  249. void MatchFinder_Init_2(CMatchFinder *p, int readData)
  250. {
  251. UInt32 i;
  252. UInt32 *hash = p->hash;
  253. UInt32 num = p->hashSizeSum;
  254. for (i = 0; i < num; i++)
  255. hash[i] = kEmptyHashValue;
  256. p->cyclicBufferPos = 0;
  257. p->buffer = p->bufferBase;
  258. p->pos = p->streamPos = p->cyclicBufferSize;
  259. p->result = SZ_OK;
  260. p->streamEndWasReached = 0;
  261. if (readData)
  262. MatchFinder_ReadBlock(p);
  263. MatchFinder_SetLimits(p);
  264. }
  265. void MatchFinder_Init(CMatchFinder *p)
  266. {
  267. MatchFinder_Init_2(p, True);
  268. }
  269. static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
  270. {
  271. return (p->pos - p->historySize - 1) & kNormalizeMask;
  272. }
  273. void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
  274. {
  275. size_t i;
  276. for (i = 0; i < numItems; i++)
  277. {
  278. UInt32 value = items[i];
  279. if (value <= subValue)
  280. value = kEmptyHashValue;
  281. else
  282. value -= subValue;
  283. items[i] = value;
  284. }
  285. }
  286. static void MatchFinder_Normalize(CMatchFinder *p)
  287. {
  288. UInt32 subValue = MatchFinder_GetSubValue(p);
  289. MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
  290. MatchFinder_ReduceOffsets(p, subValue);
  291. }
  292. static void MatchFinder_CheckLimits(CMatchFinder *p)
  293. {
  294. if (p->pos == kMaxValForNormalize)
  295. MatchFinder_Normalize(p);
  296. if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
  297. MatchFinder_CheckAndMoveAndRead(p);
  298. if (p->cyclicBufferPos == p->cyclicBufferSize)
  299. p->cyclicBufferPos = 0;
  300. MatchFinder_SetLimits(p);
  301. }
  302. static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  303. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  304. UInt32 *distances, UInt32 maxLen)
  305. {
  306. son[_cyclicBufferPos] = curMatch;
  307. for (;;)
  308. {
  309. UInt32 delta = pos - curMatch;
  310. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  311. return distances;
  312. {
  313. const Byte *pb = cur - delta;
  314. curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
  315. if (pb[maxLen] == cur[maxLen] && *pb == *cur)
  316. {
  317. UInt32 len = 0;
  318. while (++len != lenLimit)
  319. if (pb[len] != cur[len])
  320. break;
  321. if (maxLen < len)
  322. {
  323. *distances++ = maxLen = len;
  324. *distances++ = delta - 1;
  325. if (len == lenLimit)
  326. return distances;
  327. }
  328. }
  329. }
  330. }
  331. }
  332. UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  333. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  334. UInt32 *distances, UInt32 maxLen)
  335. {
  336. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  337. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  338. UInt32 len0 = 0, len1 = 0;
  339. for (;;)
  340. {
  341. UInt32 delta = pos - curMatch;
  342. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  343. {
  344. *ptr0 = *ptr1 = kEmptyHashValue;
  345. return distances;
  346. }
  347. {
  348. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  349. const Byte *pb = cur - delta;
  350. UInt32 len = (len0 < len1 ? len0 : len1);
  351. if (pb[len] == cur[len])
  352. {
  353. if (++len != lenLimit && pb[len] == cur[len])
  354. while (++len != lenLimit)
  355. if (pb[len] != cur[len])
  356. break;
  357. if (maxLen < len)
  358. {
  359. *distances++ = maxLen = len;
  360. *distances++ = delta - 1;
  361. if (len == lenLimit)
  362. {
  363. *ptr1 = pair[0];
  364. *ptr0 = pair[1];
  365. return distances;
  366. }
  367. }
  368. }
  369. if (pb[len] < cur[len])
  370. {
  371. *ptr1 = curMatch;
  372. ptr1 = pair + 1;
  373. curMatch = *ptr1;
  374. len1 = len;
  375. }
  376. else
  377. {
  378. *ptr0 = curMatch;
  379. ptr0 = pair;
  380. curMatch = *ptr0;
  381. len0 = len;
  382. }
  383. }
  384. }
  385. }
  386. static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  387. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
  388. {
  389. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  390. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  391. UInt32 len0 = 0, len1 = 0;
  392. for (;;)
  393. {
  394. UInt32 delta = pos - curMatch;
  395. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  396. {
  397. *ptr0 = *ptr1 = kEmptyHashValue;
  398. return;
  399. }
  400. {
  401. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  402. const Byte *pb = cur - delta;
  403. UInt32 len = (len0 < len1 ? len0 : len1);
  404. if (pb[len] == cur[len])
  405. {
  406. while (++len != lenLimit)
  407. if (pb[len] != cur[len])
  408. break;
  409. {
  410. if (len == lenLimit)
  411. {
  412. *ptr1 = pair[0];
  413. *ptr0 = pair[1];
  414. return;
  415. }
  416. }
  417. }
  418. if (pb[len] < cur[len])
  419. {
  420. *ptr1 = curMatch;
  421. ptr1 = pair + 1;
  422. curMatch = *ptr1;
  423. len1 = len;
  424. }
  425. else
  426. {
  427. *ptr0 = curMatch;
  428. ptr0 = pair;
  429. curMatch = *ptr0;
  430. len0 = len;
  431. }
  432. }
  433. }
  434. }
  435. #define MOVE_POS \
  436. ++p->cyclicBufferPos; \
  437. p->buffer++; \
  438. if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
  439. #define MOVE_POS_RET MOVE_POS return offset;
  440. static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
  441. #define GET_MATCHES_HEADER2(minLen, ret_op) \
  442. UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
  443. lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
  444. cur = p->buffer;
  445. #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
  446. #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
  447. #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
  448. #define GET_MATCHES_FOOTER(offset, maxLen) \
  449. offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
  450. distances + offset, maxLen) - distances); MOVE_POS_RET;
  451. #define SKIP_FOOTER \
  452. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
  453. #define UPDATE_maxLen { \
  454. ptrdiff_t diff = (ptrdiff_t)0 - d2; \
  455. const Byte *c = cur + maxLen; \
  456. const Byte *lim = cur + lenLimit; \
  457. for (; c != lim; c++) if (*(c + diff) != *c) break; \
  458. maxLen = (UInt32)(c - cur); }
  459. static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  460. {
  461. UInt32 offset;
  462. GET_MATCHES_HEADER(2)
  463. HASH2_CALC;
  464. curMatch = p->hash[hv];
  465. p->hash[hv] = p->pos;
  466. offset = 0;
  467. GET_MATCHES_FOOTER(offset, 1)
  468. }
  469. UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  470. {
  471. UInt32 offset;
  472. GET_MATCHES_HEADER(3)
  473. HASH_ZIP_CALC;
  474. curMatch = p->hash[hv];
  475. p->hash[hv] = p->pos;
  476. offset = 0;
  477. GET_MATCHES_FOOTER(offset, 2)
  478. }
  479. static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  480. {
  481. UInt32 h2, d2, maxLen, offset, pos;
  482. UInt32 *hash;
  483. GET_MATCHES_HEADER(3)
  484. HASH3_CALC;
  485. hash = p->hash;
  486. pos = p->pos;
  487. d2 = pos - hash[h2];
  488. curMatch = (hash + kFix3HashSize)[hv];
  489. hash[h2] = pos;
  490. (hash + kFix3HashSize)[hv] = pos;
  491. maxLen = 2;
  492. offset = 0;
  493. if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
  494. {
  495. UPDATE_maxLen
  496. distances[0] = maxLen;
  497. distances[1] = d2 - 1;
  498. offset = 2;
  499. if (maxLen == lenLimit)
  500. {
  501. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  502. MOVE_POS_RET;
  503. }
  504. }
  505. GET_MATCHES_FOOTER(offset, maxLen)
  506. }
  507. static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  508. {
  509. UInt32 h2, h3, d2, d3, maxLen, offset, pos;
  510. UInt32 *hash;
  511. GET_MATCHES_HEADER(4)
  512. HASH4_CALC;
  513. hash = p->hash;
  514. pos = p->pos;
  515. d2 = pos - hash[ h2];
  516. d3 = pos - (hash + kFix3HashSize)[h3];
  517. curMatch = (hash + kFix4HashSize)[hv];
  518. hash[ h2] = pos;
  519. (hash + kFix3HashSize)[h3] = pos;
  520. (hash + kFix4HashSize)[hv] = pos;
  521. maxLen = 0;
  522. offset = 0;
  523. if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
  524. {
  525. distances[0] = maxLen = 2;
  526. distances[1] = d2 - 1;
  527. offset = 2;
  528. }
  529. if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  530. {
  531. maxLen = 3;
  532. distances[(size_t)offset + 1] = d3 - 1;
  533. offset += 2;
  534. d2 = d3;
  535. }
  536. if (offset != 0)
  537. {
  538. UPDATE_maxLen
  539. distances[(size_t)offset - 2] = maxLen;
  540. if (maxLen == lenLimit)
  541. {
  542. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  543. MOVE_POS_RET;
  544. }
  545. }
  546. if (maxLen < 3)
  547. maxLen = 3;
  548. GET_MATCHES_FOOTER(offset, maxLen)
  549. }
  550. /*
  551. static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  552. {
  553. UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
  554. UInt32 *hash;
  555. GET_MATCHES_HEADER(5)
  556. HASH5_CALC;
  557. hash = p->hash;
  558. pos = p->pos;
  559. d2 = pos - hash[ h2];
  560. d3 = pos - (hash + kFix3HashSize)[h3];
  561. d4 = pos - (hash + kFix4HashSize)[h4];
  562. curMatch = (hash + kFix5HashSize)[hv];
  563. hash[ h2] = pos;
  564. (hash + kFix3HashSize)[h3] = pos;
  565. (hash + kFix4HashSize)[h4] = pos;
  566. (hash + kFix5HashSize)[hv] = pos;
  567. maxLen = 0;
  568. offset = 0;
  569. if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
  570. {
  571. distances[0] = maxLen = 2;
  572. distances[1] = d2 - 1;
  573. offset = 2;
  574. if (*(cur - d2 + 2) == cur[2])
  575. distances[0] = maxLen = 3;
  576. else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  577. {
  578. distances[2] = maxLen = 3;
  579. distances[3] = d3 - 1;
  580. offset = 4;
  581. d2 = d3;
  582. }
  583. }
  584. else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  585. {
  586. distances[0] = maxLen = 3;
  587. distances[1] = d3 - 1;
  588. offset = 2;
  589. d2 = d3;
  590. }
  591. if (d2 != d4 && d4 < p->cyclicBufferSize
  592. && *(cur - d4) == *cur
  593. && *(cur - d4 + 3) == *(cur + 3))
  594. {
  595. maxLen = 4;
  596. distances[(size_t)offset + 1] = d4 - 1;
  597. offset += 2;
  598. d2 = d4;
  599. }
  600. if (offset != 0)
  601. {
  602. UPDATE_maxLen
  603. distances[(size_t)offset - 2] = maxLen;
  604. if (maxLen == lenLimit)
  605. {
  606. SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  607. MOVE_POS_RET;
  608. }
  609. }
  610. if (maxLen < 4)
  611. maxLen = 4;
  612. GET_MATCHES_FOOTER(offset, maxLen)
  613. }
  614. */
  615. static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  616. {
  617. UInt32 h2, h3, d2, d3, maxLen, offset, pos;
  618. UInt32 *hash;
  619. GET_MATCHES_HEADER(4)
  620. HASH4_CALC;
  621. hash = p->hash;
  622. pos = p->pos;
  623. d2 = pos - hash[ h2];
  624. d3 = pos - (hash + kFix3HashSize)[h3];
  625. curMatch = (hash + kFix4HashSize)[hv];
  626. hash[ h2] = pos;
  627. (hash + kFix3HashSize)[h3] = pos;
  628. (hash + kFix4HashSize)[hv] = pos;
  629. maxLen = 0;
  630. offset = 0;
  631. if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
  632. {
  633. distances[0] = maxLen = 2;
  634. distances[1] = d2 - 1;
  635. offset = 2;
  636. }
  637. if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  638. {
  639. maxLen = 3;
  640. distances[(size_t)offset + 1] = d3 - 1;
  641. offset += 2;
  642. d2 = d3;
  643. }
  644. if (offset != 0)
  645. {
  646. UPDATE_maxLen
  647. distances[(size_t)offset - 2] = maxLen;
  648. if (maxLen == lenLimit)
  649. {
  650. p->son[p->cyclicBufferPos] = curMatch;
  651. MOVE_POS_RET;
  652. }
  653. }
  654. if (maxLen < 3)
  655. maxLen = 3;
  656. offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  657. distances + offset, maxLen) - (distances));
  658. MOVE_POS_RET
  659. }
  660. /*
  661. static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  662. {
  663. UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
  664. UInt32 *hash;
  665. GET_MATCHES_HEADER(5)
  666. HASH5_CALC;
  667. hash = p->hash;
  668. pos = p->pos;
  669. d2 = pos - hash[ h2];
  670. d3 = pos - (hash + kFix3HashSize)[h3];
  671. d4 = pos - (hash + kFix4HashSize)[h4];
  672. curMatch = (hash + kFix5HashSize)[hv];
  673. hash[ h2] = pos;
  674. (hash + kFix3HashSize)[h3] = pos;
  675. (hash + kFix4HashSize)[h4] = pos;
  676. (hash + kFix5HashSize)[hv] = pos;
  677. maxLen = 0;
  678. offset = 0;
  679. if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
  680. {
  681. distances[0] = maxLen = 2;
  682. distances[1] = d2 - 1;
  683. offset = 2;
  684. if (*(cur - d2 + 2) == cur[2])
  685. distances[0] = maxLen = 3;
  686. else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  687. {
  688. distances[2] = maxLen = 3;
  689. distances[3] = d3 - 1;
  690. offset = 4;
  691. d2 = d3;
  692. }
  693. }
  694. else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
  695. {
  696. distances[0] = maxLen = 3;
  697. distances[1] = d3 - 1;
  698. offset = 2;
  699. d2 = d3;
  700. }
  701. if (d2 != d4 && d4 < p->cyclicBufferSize
  702. && *(cur - d4) == *cur
  703. && *(cur - d4 + 3) == *(cur + 3))
  704. {
  705. maxLen = 4;
  706. distances[(size_t)offset + 1] = d4 - 1;
  707. offset += 2;
  708. d2 = d4;
  709. }
  710. if (offset != 0)
  711. {
  712. UPDATE_maxLen
  713. distances[(size_t)offset - 2] = maxLen;
  714. if (maxLen == lenLimit)
  715. {
  716. p->son[p->cyclicBufferPos] = curMatch;
  717. MOVE_POS_RET;
  718. }
  719. }
  720. if (maxLen < 4)
  721. maxLen = 4;
  722. offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  723. distances + offset, maxLen) - (distances));
  724. MOVE_POS_RET
  725. }
  726. */
  727. UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  728. {
  729. UInt32 offset;
  730. GET_MATCHES_HEADER(3)
  731. HASH_ZIP_CALC;
  732. curMatch = p->hash[hv];
  733. p->hash[hv] = p->pos;
  734. offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  735. distances, 2) - (distances));
  736. MOVE_POS_RET
  737. }
  738. static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  739. {
  740. do
  741. {
  742. SKIP_HEADER(2)
  743. HASH2_CALC;
  744. curMatch = p->hash[hv];
  745. p->hash[hv] = p->pos;
  746. SKIP_FOOTER
  747. }
  748. while (--num != 0);
  749. }
  750. void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  751. {
  752. do
  753. {
  754. SKIP_HEADER(3)
  755. HASH_ZIP_CALC;
  756. curMatch = p->hash[hv];
  757. p->hash[hv] = p->pos;
  758. SKIP_FOOTER
  759. }
  760. while (--num != 0);
  761. }
  762. static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  763. {
  764. do
  765. {
  766. UInt32 h2;
  767. UInt32 *hash;
  768. SKIP_HEADER(3)
  769. HASH3_CALC;
  770. hash = p->hash;
  771. curMatch = (hash + kFix3HashSize)[hv];
  772. hash[h2] =
  773. (hash + kFix3HashSize)[hv] = p->pos;
  774. SKIP_FOOTER
  775. }
  776. while (--num != 0);
  777. }
  778. static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  779. {
  780. do
  781. {
  782. UInt32 h2, h3;
  783. UInt32 *hash;
  784. SKIP_HEADER(4)
  785. HASH4_CALC;
  786. hash = p->hash;
  787. curMatch = (hash + kFix4HashSize)[hv];
  788. hash[ h2] =
  789. (hash + kFix3HashSize)[h3] =
  790. (hash + kFix4HashSize)[hv] = p->pos;
  791. SKIP_FOOTER
  792. }
  793. while (--num != 0);
  794. }
  795. /*
  796. static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  797. {
  798. do
  799. {
  800. UInt32 h2, h3, h4;
  801. UInt32 *hash;
  802. SKIP_HEADER(5)
  803. HASH5_CALC;
  804. hash = p->hash;
  805. curMatch = (hash + kFix5HashSize)[hv];
  806. hash[ h2] =
  807. (hash + kFix3HashSize)[h3] =
  808. (hash + kFix4HashSize)[h4] =
  809. (hash + kFix5HashSize)[hv] = p->pos;
  810. SKIP_FOOTER
  811. }
  812. while (--num != 0);
  813. }
  814. */
  815. static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  816. {
  817. do
  818. {
  819. UInt32 h2, h3;
  820. UInt32 *hash;
  821. SKIP_HEADER(4)
  822. HASH4_CALC;
  823. hash = p->hash;
  824. curMatch = (hash + kFix4HashSize)[hv];
  825. hash[ h2] =
  826. (hash + kFix3HashSize)[h3] =
  827. (hash + kFix4HashSize)[hv] = p->pos;
  828. p->son[p->cyclicBufferPos] = curMatch;
  829. MOVE_POS
  830. }
  831. while (--num != 0);
  832. }
  833. /*
  834. static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  835. {
  836. do
  837. {
  838. UInt32 h2, h3, h4;
  839. UInt32 *hash;
  840. SKIP_HEADER(5)
  841. HASH5_CALC;
  842. hash = p->hash;
  843. curMatch = hash + kFix5HashSize)[hv];
  844. hash[ h2] =
  845. (hash + kFix3HashSize)[h3] =
  846. (hash + kFix4HashSize)[h4] =
  847. (hash + kFix5HashSize)[hv] = p->pos;
  848. p->son[p->cyclicBufferPos] = curMatch;
  849. MOVE_POS
  850. }
  851. while (--num != 0);
  852. }
  853. */
  854. void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  855. {
  856. do
  857. {
  858. SKIP_HEADER(3)
  859. HASH_ZIP_CALC;
  860. curMatch = p->hash[hv];
  861. p->hash[hv] = p->pos;
  862. p->son[p->cyclicBufferPos] = curMatch;
  863. MOVE_POS
  864. }
  865. while (--num != 0);
  866. }
  867. void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
  868. {
  869. vTable->Init = (Mf_Init_Func)MatchFinder_Init;
  870. vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
  871. vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
  872. if (!p->btMode)
  873. {
  874. /* if (p->numHashBytes <= 4) */
  875. {
  876. vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
  877. vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
  878. }
  879. /*
  880. else
  881. {
  882. vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
  883. vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
  884. }
  885. */
  886. }
  887. else if (p->numHashBytes == 2)
  888. {
  889. vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
  890. vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
  891. }
  892. else if (p->numHashBytes == 3)
  893. {
  894. vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
  895. vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
  896. }
  897. else /* if (p->numHashBytes == 4) */
  898. {
  899. vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
  900. vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
  901. }
  902. /*
  903. else
  904. {
  905. vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
  906. vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
  907. }
  908. */
  909. }