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