]> git.proxmox.com Git - mirror_edk2.git/blame - 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
00f5e119 1/* LzFind.c -- Match finder for LZ algorithms\r
39bbbc87 22017-06-10 : Igor Pavlov : Public domain */\r
306bf4e2 3\r
00f5e119 4#include "Precomp.h"\r
306bf4e2 5\r
6#ifndef EFIAPI\r
306bf4e2 7#include <string.h>\r
00f5e119 8#endif\r
306bf4e2 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
00f5e119
LG
16#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))\r
17#define kMaxHistorySize ((UInt32)7 << 29)\r
306bf4e2 18\r
19#define kStartMaxLen 3\r
20\r
39bbbc87 21static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)\r
306bf4e2 22{\r
23 if (!p->directInput)\r
24 {\r
39bbbc87 25 ISzAlloc_Free(alloc, p->bufferBase);\r
00f5e119 26 p->bufferBase = NULL;\r
306bf4e2 27 }\r
28}\r
29\r
30/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */\r
31\r
39bbbc87 32static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)\r
306bf4e2 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
00f5e119 40 if (!p->bufferBase || p->blockSize != blockSize)\r
306bf4e2 41 {\r
42 LzInWindow_Free(p, alloc);\r
43 p->blockSize = blockSize;\r
39bbbc87 44 p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);\r
306bf4e2 45 }\r
00f5e119 46 return (p->bufferBase != NULL);\r
306bf4e2 47}\r
48\r
49Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }\r
306bf4e2 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
00f5e119
LG
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
306bf4e2 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
00f5e119 85\r
39bbbc87 86 p->result = ISeqInStream_Read(p->stream, dest, &size);\r
306bf4e2 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
00f5e119
LG
103 p->buffer - p->keepSizeBefore,\r
104 (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);\r
306bf4e2 105 p->buffer = p->bufferBase + p->keepSizeBefore;\r
106}\r
107\r
108int MatchFinder_NeedMove(CMatchFinder *p)\r
109{\r
00f5e119
LG
110 if (p->directInput)\r
111 return 0;\r
306bf4e2 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
306bf4e2 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
00f5e119 144 p->bufferBase = NULL;\r
306bf4e2 145 p->directInput = 0;\r
00f5e119 146 p->hash = NULL;\r
39bbbc87 147 p->expectedDataSize = (UInt64)(Int64)-1;\r
306bf4e2 148 MatchFinder_SetDefaultSettings(p);\r
149\r
150 for (i = 0; i < 256; i++)\r
151 {\r
152 UInt32 r = i;\r
00f5e119 153 unsigned j;\r
306bf4e2 154 for (j = 0; j < 8; j++)\r
39bbbc87 155 r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));\r
306bf4e2 156 p->crc[i] = r;\r
157 }\r
158}\r
159\r
39bbbc87 160static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)\r
306bf4e2 161{\r
39bbbc87 162 ISzAlloc_Free(alloc, p->hash);\r
00f5e119 163 p->hash = NULL;\r
306bf4e2 164}\r
165\r
39bbbc87 166void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)\r
306bf4e2 167{\r
168 MatchFinder_FreeThisClassMemory(p, alloc);\r
169 LzInWindow_Free(p, alloc);\r
170}\r
171\r
39bbbc87 172static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)\r
306bf4e2 173{\r
174 size_t sizeInBytes = (size_t)num * sizeof(CLzRef);\r
175 if (sizeInBytes / sizeof(CLzRef) != num)\r
00f5e119 176 return NULL;\r
39bbbc87 177 return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);\r
306bf4e2 178}\r
179\r
180int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\r
181 UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\r
39bbbc87 182 ISzAllocPtr alloc)\r
306bf4e2 183{\r
184 UInt32 sizeReserv;\r
00f5e119 185 \r
306bf4e2 186 if (historySize > kMaxHistorySize)\r
187 {\r
188 MatchFinder_Free(p, alloc);\r
189 return 0;\r
190 }\r
00f5e119 191 \r
306bf4e2 192 sizeReserv = historySize >> 1;\r
00f5e119
LG
193 if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;\r
194 else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;\r
195 \r
306bf4e2 196 sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);\r
197\r
198 p->keepSizeBefore = historySize + keepAddBufferBefore + 1;\r
199 p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;\r
00f5e119 200 \r
306bf4e2 201 /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */\r
00f5e119 202 \r
306bf4e2 203 if (LzInWindow_Create(p, sizeReserv, alloc))\r
204 {\r
00f5e119 205 UInt32 newCyclicBufferSize = historySize + 1;\r
306bf4e2 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
39bbbc87
LG
214 hs = historySize;\r
215 if (hs > p->expectedDataSize)\r
216 hs = (UInt32)p->expectedDataSize;\r
217 if (hs != 0)\r
218 hs--;\r
306bf4e2 219 hs |= (hs >> 1);\r
220 hs |= (hs >> 2);\r
221 hs |= (hs >> 4);\r
222 hs |= (hs >> 8);\r
223 hs >>= 1;\r
306bf4e2 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
00f5e119 231 /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */\r
306bf4e2 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
00f5e119
LG
243 size_t newSize;\r
244 size_t numSons;\r
306bf4e2 245 p->historySize = historySize;\r
246 p->hashSizeSum = hs;\r
247 p->cyclicBufferSize = newCyclicBufferSize;\r
00f5e119
LG
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
306bf4e2 255 return 1;\r
00f5e119 256 \r
306bf4e2 257 MatchFinder_FreeThisClassMemory(p, alloc);\r
00f5e119 258 p->numRefs = newSize;\r
306bf4e2 259 p->hash = AllocRefs(newSize, alloc);\r
00f5e119
LG
260 \r
261 if (p->hash)\r
306bf4e2 262 {\r
263 p->son = p->hash + p->hashSizeSum;\r
264 return 1;\r
265 }\r
266 }\r
267 }\r
00f5e119 268\r
306bf4e2 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
00f5e119 277 \r
306bf4e2 278 if (limit2 < limit)\r
279 limit = limit2;\r
280 limit2 = p->streamPos - p->pos;\r
00f5e119 281 \r
306bf4e2 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
00f5e119 289 \r
306bf4e2 290 if (limit2 < limit)\r
291 limit = limit2;\r
00f5e119 292 \r
306bf4e2 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
39bbbc87
LG
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
306bf4e2 324{\r
306bf4e2 325 p->cyclicBufferPos = 0;\r
326 p->buffer = p->bufferBase;\r
39bbbc87
LG
327 p->pos =\r
328 p->streamPos = p->cyclicBufferSize;\r
306bf4e2 329 p->result = SZ_OK;\r
330 p->streamEndWasReached = 0;\r
00f5e119
LG
331 \r
332 if (readData)\r
333 MatchFinder_ReadBlock(p);\r
334 \r
306bf4e2 335 MatchFinder_SetLimits(p);\r
336}\r
337\r
39bbbc87 338\r
00f5e119
LG
339void MatchFinder_Init(CMatchFinder *p)\r
340{\r
39bbbc87
LG
341 MatchFinder_Init_HighHash(p);\r
342 MatchFinder_Init_LowHash(p);\r
343 MatchFinder_Init_3(p, True);\r
00f5e119 344}\r
39bbbc87 345\r
00f5e119 346 \r
306bf4e2 347static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)\r
348{\r
349 return (p->pos - p->historySize - 1) & kNormalizeMask;\r
350}\r
351\r
00f5e119 352void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)\r
306bf4e2 353{\r
00f5e119 354 size_t i;\r
306bf4e2 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
00f5e119 369 MatchFinder_Normalize3(subValue, p->hash, p->numRefs);\r
306bf4e2 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
00f5e119 530 UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \\r
306bf4e2 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
00f5e119
LG
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
306bf4e2 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
00f5e119
LG
558 curMatch = p->hash[hv];\r
559 p->hash[hv] = p->pos;\r
306bf4e2 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
00f5e119
LG
569 curMatch = p->hash[hv];\r
570 p->hash[hv] = p->pos;\r
306bf4e2 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
00f5e119
LG
577 UInt32 h2, d2, maxLen, offset, pos;\r
578 UInt32 *hash;\r
306bf4e2 579 GET_MATCHES_HEADER(3)\r
580\r
581 HASH3_CALC;\r
582\r
00f5e119
LG
583 hash = p->hash;\r
584 pos = p->pos;\r
585\r
586 d2 = pos - hash[h2];\r
306bf4e2 587\r
39bbbc87 588 curMatch = (hash + kFix3HashSize)[hv];\r
00f5e119
LG
589 \r
590 hash[h2] = pos;\r
39bbbc87 591 (hash + kFix3HashSize)[hv] = pos;\r
306bf4e2 592\r
593 maxLen = 2;\r
594 offset = 0;\r
00f5e119
LG
595\r
596 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)\r
306bf4e2 597 {\r
00f5e119 598 UPDATE_maxLen\r
306bf4e2 599 distances[0] = maxLen;\r
00f5e119 600 distances[1] = d2 - 1;\r
306bf4e2 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
00f5e119 608 \r
306bf4e2 609 GET_MATCHES_FOOTER(offset, maxLen)\r
610}\r
611\r
612static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
613{\r
00f5e119
LG
614 UInt32 h2, h3, d2, d3, maxLen, offset, pos;\r
615 UInt32 *hash;\r
306bf4e2 616 GET_MATCHES_HEADER(4)\r
617\r
618 HASH4_CALC;\r
619\r
00f5e119
LG
620 hash = p->hash;\r
621 pos = p->pos;\r
306bf4e2 622\r
00f5e119 623 d2 = pos - hash[ h2];\r
39bbbc87 624 d3 = pos - (hash + kFix3HashSize)[h3];\r
00f5e119 625\r
39bbbc87 626 curMatch = (hash + kFix4HashSize)[hv];\r
00f5e119
LG
627\r
628 hash[ h2] = pos;\r
39bbbc87
LG
629 (hash + kFix3HashSize)[h3] = pos;\r
630 (hash + kFix4HashSize)[hv] = pos;\r
00f5e119
LG
631\r
632 maxLen = 0;\r
306bf4e2 633 offset = 0;\r
00f5e119
LG
634 \r
635 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)\r
306bf4e2 636 {\r
637 distances[0] = maxLen = 2;\r
00f5e119 638 distances[1] = d2 - 1;\r
306bf4e2 639 offset = 2;\r
640 }\r
00f5e119
LG
641 \r
642 if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)\r
306bf4e2 643 {\r
644 maxLen = 3;\r
39bbbc87 645 distances[(size_t)offset + 1] = d3 - 1;\r
306bf4e2 646 offset += 2;\r
00f5e119 647 d2 = d3;\r
306bf4e2 648 }\r
00f5e119 649 \r
306bf4e2 650 if (offset != 0)\r
651 {\r
00f5e119 652 UPDATE_maxLen\r
39bbbc87 653 distances[(size_t)offset - 2] = maxLen;\r
306bf4e2 654 if (maxLen == lenLimit)\r
655 {\r
656 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));\r
657 MOVE_POS_RET;\r
658 }\r
659 }\r
00f5e119 660 \r
306bf4e2 661 if (maxLen < 3)\r
662 maxLen = 3;\r
00f5e119 663 \r
306bf4e2 664 GET_MATCHES_FOOTER(offset, maxLen)\r
665}\r
666\r
00f5e119
LG
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
39bbbc87
LG
680 d3 = pos - (hash + kFix3HashSize)[h3];\r
681 d4 = pos - (hash + kFix4HashSize)[h4];\r
00f5e119 682\r
39bbbc87 683 curMatch = (hash + kFix5HashSize)[hv];\r
00f5e119
LG
684\r
685 hash[ h2] = pos;\r
39bbbc87
LG
686 (hash + kFix3HashSize)[h3] = pos;\r
687 (hash + kFix4HashSize)[h4] = pos;\r
688 (hash + kFix5HashSize)[hv] = pos;\r
00f5e119
LG
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
39bbbc87 721 distances[(size_t)offset + 1] = d4 - 1;\r
00f5e119
LG
722 offset += 2;\r
723 d2 = d4;\r
724 }\r
725 \r
726 if (offset != 0)\r
727 {\r
728 UPDATE_maxLen\r
39bbbc87 729 distances[(size_t)offset - 2] = maxLen;\r
00f5e119
LG
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
306bf4e2 744static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
745{\r
00f5e119
LG
746 UInt32 h2, h3, d2, d3, maxLen, offset, pos;\r
747 UInt32 *hash;\r
306bf4e2 748 GET_MATCHES_HEADER(4)\r
749\r
750 HASH4_CALC;\r
751\r
00f5e119
LG
752 hash = p->hash;\r
753 pos = p->pos;\r
754 \r
755 d2 = pos - hash[ h2];\r
39bbbc87 756 d3 = pos - (hash + kFix3HashSize)[h3];\r
00f5e119 757 \r
39bbbc87 758 curMatch = (hash + kFix4HashSize)[hv];\r
306bf4e2 759\r
00f5e119 760 hash[ h2] = pos;\r
39bbbc87
LG
761 (hash + kFix3HashSize)[h3] = pos;\r
762 (hash + kFix4HashSize)[hv] = pos;\r
306bf4e2 763\r
00f5e119 764 maxLen = 0;\r
306bf4e2 765 offset = 0;\r
00f5e119
LG
766\r
767 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)\r
306bf4e2 768 {\r
769 distances[0] = maxLen = 2;\r
00f5e119 770 distances[1] = d2 - 1;\r
306bf4e2 771 offset = 2;\r
772 }\r
00f5e119
LG
773 \r
774 if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)\r
306bf4e2 775 {\r
776 maxLen = 3;\r
39bbbc87 777 distances[(size_t)offset + 1] = d3 - 1;\r
306bf4e2 778 offset += 2;\r
00f5e119 779 d2 = d3;\r
306bf4e2 780 }\r
00f5e119 781 \r
306bf4e2 782 if (offset != 0)\r
783 {\r
00f5e119 784 UPDATE_maxLen\r
39bbbc87 785 distances[(size_t)offset - 2] = maxLen;\r
306bf4e2 786 if (maxLen == lenLimit)\r
787 {\r
788 p->son[p->cyclicBufferPos] = curMatch;\r
789 MOVE_POS_RET;\r
790 }\r
791 }\r
00f5e119 792 \r
306bf4e2 793 if (maxLen < 3)\r
794 maxLen = 3;\r
00f5e119 795\r
306bf4e2 796 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\r
00f5e119 797 distances + offset, maxLen) - (distances));\r
306bf4e2 798 MOVE_POS_RET\r
799}\r
800\r
00f5e119
LG
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
39bbbc87
LG
814 d3 = pos - (hash + kFix3HashSize)[h3];\r
815 d4 = pos - (hash + kFix4HashSize)[h4];\r
00f5e119 816\r
39bbbc87 817 curMatch = (hash + kFix5HashSize)[hv];\r
00f5e119
LG
818\r
819 hash[ h2] = pos;\r
39bbbc87
LG
820 (hash + kFix3HashSize)[h3] = pos;\r
821 (hash + kFix4HashSize)[h4] = pos;\r
822 (hash + kFix5HashSize)[hv] = pos;\r
00f5e119
LG
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
39bbbc87 855 distances[(size_t)offset + 1] = d4 - 1;\r
00f5e119
LG
856 offset += 2;\r
857 d2 = d4;\r
858 }\r
859 \r
860 if (offset != 0)\r
861 {\r
862 UPDATE_maxLen\r
39bbbc87 863 distances[(size_t)offset - 2] = maxLen;\r
00f5e119
LG
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
306bf4e2 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
00f5e119
LG
885 curMatch = p->hash[hv];\r
886 p->hash[hv] = p->pos;\r
306bf4e2 887 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\r
00f5e119 888 distances, 2) - (distances));\r
306bf4e2 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
00f5e119
LG
898 curMatch = p->hash[hv];\r
899 p->hash[hv] = p->pos;\r
306bf4e2 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
00f5e119
LG
911 curMatch = p->hash[hv];\r
912 p->hash[hv] = p->pos;\r
306bf4e2 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
00f5e119
LG
922 UInt32 h2;\r
923 UInt32 *hash;\r
306bf4e2 924 SKIP_HEADER(3)\r
925 HASH3_CALC;\r
00f5e119 926 hash = p->hash;\r
39bbbc87 927 curMatch = (hash + kFix3HashSize)[hv];\r
00f5e119 928 hash[h2] =\r
39bbbc87 929 (hash + kFix3HashSize)[hv] = p->pos;\r
306bf4e2 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
00f5e119
LG
939 UInt32 h2, h3;\r
940 UInt32 *hash;\r
306bf4e2 941 SKIP_HEADER(4)\r
942 HASH4_CALC;\r
00f5e119 943 hash = p->hash;\r
39bbbc87 944 curMatch = (hash + kFix4HashSize)[hv];\r
00f5e119 945 hash[ h2] =\r
39bbbc87
LG
946 (hash + kFix3HashSize)[h3] =\r
947 (hash + kFix4HashSize)[hv] = p->pos;\r
00f5e119
LG
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
39bbbc87 963 curMatch = (hash + kFix5HashSize)[hv];\r
00f5e119 964 hash[ h2] =\r
39bbbc87
LG
965 (hash + kFix3HashSize)[h3] =\r
966 (hash + kFix4HashSize)[h4] =\r
967 (hash + kFix5HashSize)[hv] = p->pos;\r
306bf4e2 968 SKIP_FOOTER\r
969 }\r
970 while (--num != 0);\r
971}\r
00f5e119 972*/\r
306bf4e2 973\r
974static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
975{\r
976 do\r
977 {\r
00f5e119
LG
978 UInt32 h2, h3;\r
979 UInt32 *hash;\r
306bf4e2 980 SKIP_HEADER(4)\r
981 HASH4_CALC;\r
00f5e119 982 hash = p->hash;\r
39bbbc87 983 curMatch = (hash + kFix4HashSize)[hv];\r
00f5e119 984 hash[ h2] =\r
39bbbc87
LG
985 (hash + kFix3HashSize)[h3] =\r
986 (hash + kFix4HashSize)[hv] = p->pos;\r
00f5e119
LG
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
39bbbc87 1003 curMatch = hash + kFix5HashSize)[hv];\r
00f5e119 1004 hash[ h2] =\r
39bbbc87
LG
1005 (hash + kFix3HashSize)[h3] =\r
1006 (hash + kFix4HashSize)[h4] =\r
1007 (hash + kFix5HashSize)[hv] = p->pos;\r
306bf4e2 1008 p->son[p->cyclicBufferPos] = curMatch;\r
1009 MOVE_POS\r
1010 }\r
1011 while (--num != 0);\r
1012}\r
00f5e119 1013*/\r
306bf4e2 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
00f5e119
LG
1021 curMatch = p->hash[hv];\r
1022 p->hash[hv] = p->pos;\r
306bf4e2 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
306bf4e2 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
00f5e119
LG
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
306bf4e2 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
00f5e119 1059 else /* if (p->numHashBytes == 4) */\r
306bf4e2 1060 {\r
1061 vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;\r
1062 vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;\r
1063 }\r
00f5e119
LG
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
306bf4e2 1071}\r