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