Coverage Report

Created: 2025-07-18 06:18

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