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