Subversion Repositories spk

Rev

Details | Last modification | View Log | RSS feed

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