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