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