Coverage Report

Created: 2024-07-27 06:17

/src/lzma-fuzz/sdk/C/Lzma2Enc.c
Line
Count
Source (jump to first uncovered line)
1
/* Lzma2Enc.c -- LZMA2 Encoder
2
2018-07-04 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
#include <string.h>
7
8
/* #define _7ZIP_ST */
9
10
#include "Lzma2Enc.h"
11
12
#ifndef _7ZIP_ST
13
#include "MtCoder.h"
14
#else
15
77.7k
#define MTCODER__THREADS_MAX 1
16
#endif
17
18
8.08k
#define LZMA2_CONTROL_LZMA (1 << 7)
19
2.73k
#define LZMA2_CONTROL_COPY_NO_RESET 2
20
1.68k
#define LZMA2_CONTROL_COPY_RESET_DIC 1
21
#define LZMA2_CONTROL_EOF 0
22
23
7.77k
#define LZMA2_LCLP_MAX 4
24
25
194k
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
26
27
24.7k
#define LZMA2_PACK_SIZE_MAX (1 << 16)
28
4.42k
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
29
20.2k
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
30
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
31
32
20.2k
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
33
34
35
#define PRF(x) /* x */
36
37
38
/* ---------- CLimitedSeqInStream ---------- */
39
40
typedef struct
41
{
42
  ISeqInStream vt;
43
  ISeqInStream *realStream;
44
  UInt64 limit;
45
  UInt64 processed;
46
  int finished;
47
} CLimitedSeqInStream;
48
49
static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
50
7.77k
{
51
7.77k
  p->limit = (UInt64)(Int64)-1;
52
7.77k
  p->processed = 0;
53
7.77k
  p->finished = 0;
54
7.77k
}
55
56
static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
57
17.4k
{
58
17.4k
  CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);
59
17.4k
  size_t size2 = *size;
60
17.4k
  SRes res = SZ_OK;
61
  
62
17.4k
  if (p->limit != (UInt64)(Int64)-1)
63
0
  {
64
0
    UInt64 rem = p->limit - p->processed;
65
0
    if (size2 > rem)
66
0
      size2 = (size_t)rem;
67
0
  }
68
17.4k
  if (size2 != 0)
69
17.4k
  {
70
17.4k
    res = ISeqInStream_Read(p->realStream, data, &size2);
71
17.4k
    p->finished = (size2 == 0 ? 1 : 0);
72
17.4k
    p->processed += size2;
73
17.4k
  }
74
17.4k
  *size = size2;
75
17.4k
  return res;
76
17.4k
}
77
78
79
/* ---------- CLzma2EncInt ---------- */
80
81
typedef struct
82
{
83
  CLzmaEncHandle enc;
84
  Byte propsAreSet;
85
  Byte propsByte;
86
  Byte needInitState;
87
  Byte needInitProp;
88
  UInt64 srcPos;
89
} CLzma2EncInt;
90
91
92
static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)
93
7.77k
{
94
7.77k
  if (!p->propsAreSet)
95
7.77k
  {
96
7.77k
    SizeT propsSize = LZMA_PROPS_SIZE;
97
7.77k
    Byte propsEncoded[LZMA_PROPS_SIZE];
98
7.77k
    RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
99
7.77k
    RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
100
7.77k
    p->propsByte = propsEncoded[0];
101
7.77k
    p->propsAreSet = True;
102
7.77k
  }
103
7.77k
  return SZ_OK;
104
7.77k
}
105
106
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
107
7.77k
{
108
7.77k
  p->srcPos = 0;
109
7.77k
  p->needInitState = True;
110
7.77k
  p->needInitProp = True;
111
7.77k
}
112
113
114
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
115
    ISzAllocPtr alloc, ISzAllocPtr allocBig);
116
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
117
    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
118
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
119
    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
120
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
121
void LzmaEnc_Finish(CLzmaEncHandle pp);
122
void LzmaEnc_SaveState(CLzmaEncHandle pp);
123
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
124
125
/*
126
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp);
127
*/
128
129
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
130
    size_t *packSizeRes, ISeqOutStream *outStream)
131
20.2k
{
132
20.2k
  size_t packSizeLimit = *packSizeRes;
133
20.2k
  size_t packSize = packSizeLimit;
134
20.2k
  UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
135
20.2k
  unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
136
20.2k
  BoolInt useCopyBlock;
137
20.2k
  SRes res;
138
139
20.2k
  *packSizeRes = 0;
140
20.2k
  if (packSize < lzHeaderSize)
141
0
    return SZ_ERROR_OUTPUT_EOF;
142
20.2k
  packSize -= lzHeaderSize;
143
  
144
20.2k
  LzmaEnc_SaveState(p->enc);
145
20.2k
  res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
146
20.2k
      outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
147
  
148
20.2k
  PRF(printf("\npackSize = %7d unpackSize = %7d  ", packSize, unpackSize));
149
150
20.2k
  if (unpackSize == 0)
151
7.77k
    return res;
152
153
12.5k
  if (res == SZ_OK)
154
12.5k
    useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
155
0
  else
156
0
  {
157
0
    if (res != SZ_ERROR_OUTPUT_EOF)
158
0
      return res;
159
0
    res = SZ_OK;
160
0
    useCopyBlock = True;
161
0
  }
162
163
12.5k
  if (useCopyBlock)
164
4.42k
  {
165
4.42k
    size_t destPos = 0;
166
4.42k
    PRF(printf("################# COPY           "));
167
168
8.84k
    while (unpackSize > 0)
169
4.42k
    {
170
4.42k
      UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
171
4.42k
      if (packSizeLimit - destPos < u + 3)
172
0
        return SZ_ERROR_OUTPUT_EOF;
173
4.42k
      outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
174
4.42k
      outBuf[destPos++] = (Byte)((u - 1) >> 8);
175
4.42k
      outBuf[destPos++] = (Byte)(u - 1);
176
4.42k
      memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
177
4.42k
      unpackSize -= u;
178
4.42k
      destPos += u;
179
4.42k
      p->srcPos += u;
180
      
181
4.42k
      if (outStream)
182
4.42k
      {
183
4.42k
        *packSizeRes += destPos;
184
4.42k
        if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
185
0
          return SZ_ERROR_WRITE;
186
4.42k
        destPos = 0;
187
4.42k
      }
188
0
      else
189
0
        *packSizeRes = destPos;
190
      /* needInitState = True; */
191
4.42k
    }
192
    
193
4.42k
    LzmaEnc_RestoreState(p->enc);
194
4.42k
    return SZ_OK;
195
4.42k
  }
196
197
8.08k
  {
198
8.08k
    size_t destPos = 0;
199
8.08k
    UInt32 u = unpackSize - 1;
200
8.08k
    UInt32 pm = (UInt32)(packSize - 1);
201
8.08k
    unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
202
203
8.08k
    PRF(printf("               "));
204
205
8.08k
    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
206
8.08k
    outBuf[destPos++] = (Byte)(u >> 8);
207
8.08k
    outBuf[destPos++] = (Byte)u;
208
8.08k
    outBuf[destPos++] = (Byte)(pm >> 8);
209
8.08k
    outBuf[destPos++] = (Byte)pm;
210
    
211
8.08k
    if (p->needInitProp)
212
6.23k
      outBuf[destPos++] = p->propsByte;
213
    
214
8.08k
    p->needInitProp = False;
215
8.08k
    p->needInitState = False;
216
8.08k
    destPos += packSize;
217
8.08k
    p->srcPos += unpackSize;
218
219
8.08k
    if (outStream)
220
8.08k
      if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
221
0
        return SZ_ERROR_WRITE;
222
    
223
8.08k
    *packSizeRes = destPos;
224
8.08k
    return SZ_OK;
225
8.08k
  }
226
8.08k
}
227
228
229
/* ---------- Lzma2 Props ---------- */
230
231
void Lzma2EncProps_Init(CLzma2EncProps *p)
232
23.3k
{
233
23.3k
  LzmaEncProps_Init(&p->lzmaProps);
234
23.3k
  p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;
235
23.3k
  p->numBlockThreads_Reduced = -1;
236
23.3k
  p->numBlockThreads_Max = -1;
237
23.3k
  p->numTotalThreads = -1;
238
23.3k
}
239
240
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
241
31.1k
{
242
31.1k
  UInt64 fileSize;
243
31.1k
  int t1, t1n, t2, t2r, t3;
244
31.1k
  {
245
31.1k
    CLzmaEncProps lzmaProps = p->lzmaProps;
246
31.1k
    LzmaEncProps_Normalize(&lzmaProps);
247
31.1k
    t1n = lzmaProps.numThreads;
248
31.1k
  }
249
250
31.1k
  t1 = p->lzmaProps.numThreads;
251
31.1k
  t2 = p->numBlockThreads_Max;
252
31.1k
  t3 = p->numTotalThreads;
253
254
31.1k
  if (t2 > MTCODER__THREADS_MAX)
255
0
    t2 = MTCODER__THREADS_MAX;
256
257
31.1k
  if (t3 <= 0)
258
31.1k
  {
259
31.1k
    if (t2 <= 0)
260
23.3k
      t2 = 1;
261
31.1k
    t3 = t1n * t2;
262
31.1k
  }
263
0
  else if (t2 <= 0)
264
0
  {
265
0
    t2 = t3 / t1n;
266
0
    if (t2 == 0)
267
0
    {
268
0
      t1 = 1;
269
0
      t2 = t3;
270
0
    }
271
0
    if (t2 > MTCODER__THREADS_MAX)
272
0
      t2 = MTCODER__THREADS_MAX;
273
0
  }
274
0
  else if (t1 <= 0)
275
0
  {
276
0
    t1 = t3 / t2;
277
0
    if (t1 == 0)
278
0
      t1 = 1;
279
0
  }
280
0
  else
281
0
    t3 = t1n * t2;
282
283
31.1k
  p->lzmaProps.numThreads = t1;
284
285
31.1k
  t2r = t2;
286
287
31.1k
  fileSize = p->lzmaProps.reduceSize;
288
289
31.1k
  if (   p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
290
31.1k
      && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
291
31.1k
      && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
292
0
    p->lzmaProps.reduceSize = p->blockSize;
293
294
31.1k
  LzmaEncProps_Normalize(&p->lzmaProps);
295
296
31.1k
  p->lzmaProps.reduceSize = fileSize;
297
298
31.1k
  t1 = p->lzmaProps.numThreads;
299
300
31.1k
  if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
301
7.77k
  {
302
7.77k
    t2r = t2 = 1;
303
7.77k
    t3 = t1;
304
7.77k
  }
305
23.3k
  else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)
306
23.3k
  {
307
    /* if there is no block multi-threading, we use SOLID block */
308
23.3k
    p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
309
23.3k
  }
310
0
  else
311
0
  {
312
0
    if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
313
0
    {
314
0
      const UInt32 kMinSize = (UInt32)1 << 20;
315
0
      const UInt32 kMaxSize = (UInt32)1 << 28;
316
0
      const UInt32 dictSize = p->lzmaProps.dictSize;
317
0
      UInt64 blockSize = (UInt64)dictSize << 2;
318
0
      if (blockSize < kMinSize) blockSize = kMinSize;
319
0
      if (blockSize > kMaxSize) blockSize = kMaxSize;
320
0
      if (blockSize < dictSize) blockSize = dictSize;
321
0
      blockSize += (kMinSize - 1);
322
0
      blockSize &= ~(UInt64)(kMinSize - 1);
323
0
      p->blockSize = blockSize;
324
0
    }
325
    
326
0
    if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
327
0
    {
328
0
      UInt64 numBlocks = fileSize / p->blockSize;
329
0
      if (numBlocks * p->blockSize != fileSize)
330
0
        numBlocks++;
331
0
      if (numBlocks < (unsigned)t2)
332
0
      {
333
0
        t2r = (unsigned)numBlocks;
334
0
        if (t2r == 0)
335
0
          t2r = 1;
336
0
        t3 = t1 * t2r;
337
0
      }
338
0
    }
339
0
  }
340
  
341
31.1k
  p->numBlockThreads_Max = t2;
342
31.1k
  p->numBlockThreads_Reduced = t2r;
343
31.1k
  p->numTotalThreads = t3;
344
31.1k
}
345
346
347
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
348
20.2k
{
349
20.2k
  return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
350
20.2k
}
351
352
353
/* ---------- Lzma2 ---------- */
354
355
typedef struct
356
{
357
  Byte propEncoded;
358
  CLzma2EncProps props;
359
  UInt64 expectedDataSize;
360
  
361
  Byte *tempBufLzma;
362
363
  ISzAllocPtr alloc;
364
  ISzAllocPtr allocBig;
365
366
  CLzma2EncInt coders[MTCODER__THREADS_MAX];
367
368
  #ifndef _7ZIP_ST
369
  
370
  ISeqOutStream *outStream;
371
  Byte *outBuf;
372
  size_t outBuf_Rem;   /* remainder in outBuf */
373
374
  size_t outBufSize;   /* size of allocated outBufs[i] */
375
  size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];
376
  BoolInt mtCoder_WasConstructed;
377
  CMtCoder mtCoder;
378
  Byte *outBufs[MTCODER__BLOCKS_MAX];
379
380
  #endif
381
382
} CLzma2Enc;
383
384
385
386
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
387
7.77k
{
388
7.77k
  CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
389
7.77k
  if (!p)
390
0
    return NULL;
391
7.77k
  Lzma2EncProps_Init(&p->props);
392
7.77k
  Lzma2EncProps_Normalize(&p->props);
393
7.77k
  p->expectedDataSize = (UInt64)(Int64)-1;
394
7.77k
  p->tempBufLzma = NULL;
395
7.77k
  p->alloc = alloc;
396
7.77k
  p->allocBig = allocBig;
397
7.77k
  {
398
7.77k
    unsigned i;
399
15.5k
    for (i = 0; i < MTCODER__THREADS_MAX; i++)
400
7.77k
      p->coders[i].enc = NULL;
401
7.77k
  }
402
  
403
  #ifndef _7ZIP_ST
404
  p->mtCoder_WasConstructed = False;
405
  {
406
    unsigned i;
407
    for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
408
      p->outBufs[i] = NULL;
409
    p->outBufSize = 0;
410
  }
411
  #endif
412
413
7.77k
  return p;
414
7.77k
}
415
416
417
#ifndef _7ZIP_ST
418
419
static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
420
{
421
  unsigned i;
422
  for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
423
    if (p->outBufs[i])
424
    {
425
      ISzAlloc_Free(p->alloc, p->outBufs[i]);
426
      p->outBufs[i] = NULL;
427
    }
428
  p->outBufSize = 0;
429
}
430
431
#endif
432
433
434
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
435
7.77k
{
436
7.77k
  CLzma2Enc *p = (CLzma2Enc *)pp;
437
7.77k
  unsigned i;
438
15.5k
  for (i = 0; i < MTCODER__THREADS_MAX; i++)
439
7.77k
  {
440
7.77k
    CLzma2EncInt *t = &p->coders[i];
441
7.77k
    if (t->enc)
442
7.77k
    {
443
7.77k
      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
444
7.77k
      t->enc = NULL;
445
7.77k
    }
446
7.77k
  }
447
448
449
  #ifndef _7ZIP_ST
450
  if (p->mtCoder_WasConstructed)
451
  {
452
    MtCoder_Destruct(&p->mtCoder);
453
    p->mtCoder_WasConstructed = False;
454
  }
455
  Lzma2Enc_FreeOutBufs(p);
456
  #endif
457
458
7.77k
  ISzAlloc_Free(p->alloc, p->tempBufLzma);
459
7.77k
  p->tempBufLzma = NULL;
460
461
7.77k
  ISzAlloc_Free(p->alloc, pp);
462
7.77k
}
463
464
465
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
466
7.77k
{
467
7.77k
  CLzma2Enc *p = (CLzma2Enc *)pp;
468
7.77k
  CLzmaEncProps lzmaProps = props->lzmaProps;
469
7.77k
  LzmaEncProps_Normalize(&lzmaProps);
470
7.77k
  if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
471
0
    return SZ_ERROR_PARAM;
472
7.77k
  p->props = *props;
473
7.77k
  Lzma2EncProps_Normalize(&p->props);
474
7.77k
  return SZ_OK;
475
7.77k
}
476
477
478
void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
479
0
{
480
0
  CLzma2Enc *p = (CLzma2Enc *)pp;
481
0
  p->expectedDataSize = expectedDataSiize;
482
0
}
483
484
485
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
486
7.77k
{
487
7.77k
  CLzma2Enc *p = (CLzma2Enc *)pp;
488
7.77k
  unsigned i;
489
7.77k
  UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
490
194k
  for (i = 0; i < 40; i++)
491
194k
    if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
492
7.77k
      break;
493
7.77k
  return (Byte)i;
494
7.77k
}
495
496
497
static SRes Lzma2Enc_EncodeMt1(
498
    CLzma2Enc *me,
499
    CLzma2EncInt *p,
500
    ISeqOutStream *outStream,
501
    Byte *outBuf, size_t *outBufSize,
502
    ISeqInStream *inStream,
503
    const Byte *inData, size_t inDataSize,
504
    int finished,
505
    ICompressProgress *progress)
506
7.77k
{
507
7.77k
  UInt64 unpackTotal = 0;
508
7.77k
  UInt64 packTotal = 0;
509
7.77k
  size_t outLim = 0;
510
7.77k
  CLimitedSeqInStream limitedInStream;
511
512
7.77k
  if (outBuf)
513
0
  {
514
0
    outLim = *outBufSize;
515
0
    *outBufSize = 0;
516
0
  }
517
518
7.77k
  if (!p->enc)
519
7.77k
  {
520
7.77k
    p->propsAreSet = False;
521
7.77k
    p->enc = LzmaEnc_Create(me->alloc);
522
7.77k
    if (!p->enc)
523
0
      return SZ_ERROR_MEM;
524
7.77k
  }
525
526
7.77k
  limitedInStream.realStream = inStream;
527
7.77k
  if (inStream)
528
7.77k
  {
529
7.77k
    limitedInStream.vt.Read = LimitedSeqInStream_Read;
530
7.77k
  }
531
  
532
7.77k
  if (!outBuf)
533
7.77k
  {
534
    // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
535
7.77k
    if (!me->tempBufLzma)
536
7.77k
    {
537
7.77k
      me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
538
7.77k
      if (!me->tempBufLzma)
539
0
        return SZ_ERROR_MEM;
540
7.77k
    }
541
7.77k
  }
542
543
7.77k
  RINOK(Lzma2EncInt_InitStream(p, &me->props));
544
545
7.77k
  for (;;)
546
7.77k
  {
547
7.77k
    SRes res = SZ_OK;
548
7.77k
    size_t inSizeCur = 0;
549
550
7.77k
    Lzma2EncInt_InitBlock(p);
551
    
552
7.77k
    LimitedSeqInStream_Init(&limitedInStream);
553
7.77k
    limitedInStream.limit = me->props.blockSize;
554
555
7.77k
    if (inStream)
556
7.77k
    {
557
7.77k
      UInt64 expected = (UInt64)(Int64)-1;
558
      // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
559
7.77k
      if (me->expectedDataSize != (UInt64)(Int64)-1
560
7.77k
          && me->expectedDataSize >= unpackTotal)
561
0
        expected = me->expectedDataSize - unpackTotal;
562
7.77k
      if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
563
7.77k
          && expected > me->props.blockSize)
564
0
        expected = (size_t)me->props.blockSize;
565
566
7.77k
      LzmaEnc_SetDataSize(p->enc, expected);
567
568
7.77k
      RINOK(LzmaEnc_PrepareForLzma2(p->enc,
569
7.77k
          &limitedInStream.vt,
570
7.77k
          LZMA2_KEEP_WINDOW_SIZE,
571
7.77k
          me->alloc,
572
7.77k
          me->allocBig));
573
7.77k
    }
574
0
    else
575
0
    {
576
0
      inSizeCur = inDataSize - (size_t)unpackTotal;
577
0
      if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
578
0
          && inSizeCur > me->props.blockSize)
579
0
        inSizeCur = (size_t)me->props.blockSize;
580
    
581
      // LzmaEnc_SetDataSize(p->enc, inSizeCur);
582
      
583
0
      RINOK(LzmaEnc_MemPrepare(p->enc,
584
0
          inData + (size_t)unpackTotal, inSizeCur,
585
0
          LZMA2_KEEP_WINDOW_SIZE,
586
0
          me->alloc,
587
0
          me->allocBig));
588
0
    }
589
590
7.77k
    for (;;)
591
20.2k
    {
592
20.2k
      size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
593
20.2k
      if (outBuf)
594
0
        packSize = outLim - (size_t)packTotal;
595
      
596
20.2k
      res = Lzma2EncInt_EncodeSubblock(p,
597
20.2k
          outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
598
20.2k
          outBuf ? NULL : outStream);
599
      
600
20.2k
      if (res != SZ_OK)
601
0
        break;
602
603
20.2k
      packTotal += packSize;
604
20.2k
      if (outBuf)
605
0
        *outBufSize = (size_t)packTotal;
606
      
607
20.2k
      res = Progress(progress, unpackTotal + p->srcPos, packTotal);
608
20.2k
      if (res != SZ_OK)
609
0
        break;
610
611
      /*
612
      if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
613
        break;
614
      */
615
616
20.2k
      if (packSize == 0)
617
7.77k
        break;
618
20.2k
    }
619
    
620
7.77k
    LzmaEnc_Finish(p->enc);
621
    
622
7.77k
    unpackTotal += p->srcPos;
623
    
624
7.77k
    RINOK(res);
625
626
7.77k
    if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
627
0
      return SZ_ERROR_FAIL;
628
    
629
7.77k
    if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
630
7.77k
    {
631
7.77k
      if (finished)
632
7.77k
      {
633
7.77k
        if (outBuf)
634
0
        {
635
0
          size_t destPos = *outBufSize;
636
0
          if (destPos >= outLim)
637
0
            return SZ_ERROR_OUTPUT_EOF;
638
0
          outBuf[destPos] = 0;
639
0
          *outBufSize = destPos + 1;
640
0
        }
641
7.77k
        else
642
7.77k
        {
643
7.77k
          Byte b = 0;
644
7.77k
          if (ISeqOutStream_Write(outStream, &b, 1) != 1)
645
0
            return SZ_ERROR_WRITE;
646
7.77k
        }
647
7.77k
      }
648
7.77k
      return SZ_OK;
649
7.77k
    }
650
7.77k
  }
651
7.77k
}
652
653
654
655
#ifndef _7ZIP_ST
656
657
static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,
658
    const Byte *src, size_t srcSize, int finished)
659
{
660
  CLzma2Enc *me = (CLzma2Enc *)pp;
661
  size_t destSize = me->outBufSize;
662
  SRes res;
663
  CMtProgressThunk progressThunk;
664
665
  Byte *dest = me->outBufs[outBufIndex];
666
667
  me->outBufsDataSizes[outBufIndex] = 0;
668
669
  if (!dest)
670
  {
671
    dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
672
    if (!dest)
673
      return SZ_ERROR_MEM;
674
    me->outBufs[outBufIndex] = dest;
675
  }
676
677
  MtProgressThunk_CreateVTable(&progressThunk);
678
  progressThunk.mtProgress = &me->mtCoder.mtProgress;
679
  progressThunk.inSize = 0;
680
  progressThunk.outSize = 0;
681
682
  res = Lzma2Enc_EncodeMt1(me,
683
      &me->coders[coderIndex],
684
      NULL, dest, &destSize,
685
      NULL, src, srcSize,
686
      finished,
687
      &progressThunk.vt);
688
689
  me->outBufsDataSizes[outBufIndex] = destSize;
690
691
  return res;
692
}
693
694
695
static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)
696
{
697
  CLzma2Enc *me = (CLzma2Enc *)pp;
698
  size_t size = me->outBufsDataSizes[outBufIndex];
699
  const Byte *data = me->outBufs[outBufIndex];
700
  
701
  if (me->outStream)
702
    return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
703
  
704
  if (size > me->outBuf_Rem)
705
    return SZ_ERROR_OUTPUT_EOF;
706
  memcpy(me->outBuf, data, size);
707
  me->outBuf_Rem -= size;
708
  me->outBuf += size;
709
  return SZ_OK;
710
}
711
712
#endif
713
714
715
716
SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
717
    ISeqOutStream *outStream,
718
    Byte *outBuf, size_t *outBufSize,
719
    ISeqInStream *inStream,
720
    const Byte *inData, size_t inDataSize,
721
    ICompressProgress *progress)
722
7.77k
{
723
7.77k
  CLzma2Enc *p = (CLzma2Enc *)pp;
724
725
7.77k
  if (inStream && inData)
726
0
    return SZ_ERROR_PARAM;
727
728
7.77k
  if (outStream && outBuf)
729
0
    return SZ_ERROR_PARAM;
730
731
7.77k
  {
732
7.77k
    unsigned i;
733
15.5k
    for (i = 0; i < MTCODER__THREADS_MAX; i++)
734
7.77k
      p->coders[i].propsAreSet = False;
735
7.77k
  }
736
737
  #ifndef _7ZIP_ST
738
  
739
  if (p->props.numBlockThreads_Reduced > 1)
740
  {
741
    IMtCoderCallback2 vt;
742
743
    if (!p->mtCoder_WasConstructed)
744
    {
745
      p->mtCoder_WasConstructed = True;
746
      MtCoder_Construct(&p->mtCoder);
747
    }
748
749
    vt.Code = Lzma2Enc_MtCallback_Code;
750
    vt.Write = Lzma2Enc_MtCallback_Write;
751
752
    p->outStream = outStream;
753
    p->outBuf = NULL;
754
    p->outBuf_Rem = 0;
755
    if (!outStream)
756
    {
757
      p->outBuf = outBuf;
758
      p->outBuf_Rem = *outBufSize;
759
      *outBufSize = 0;
760
    }
761
762
    p->mtCoder.allocBig = p->allocBig;
763
    p->mtCoder.progress = progress;
764
    p->mtCoder.inStream = inStream;
765
    p->mtCoder.inData = inData;
766
    p->mtCoder.inDataSize = inDataSize;
767
    p->mtCoder.mtCallback = &vt;
768
    p->mtCoder.mtCallbackObject = p;
769
770
    p->mtCoder.blockSize = (size_t)p->props.blockSize;
771
    if (p->mtCoder.blockSize != p->props.blockSize)
772
      return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
773
774
    {
775
      size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
776
      if (destBlockSize < p->mtCoder.blockSize)
777
        return SZ_ERROR_PARAM;
778
      if (p->outBufSize != destBlockSize)
779
        Lzma2Enc_FreeOutBufs(p);
780
      p->outBufSize = destBlockSize;
781
    }
782
783
    p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;
784
    p->mtCoder.expectedDataSize = p->expectedDataSize;
785
    
786
    {
787
      SRes res = MtCoder_Code(&p->mtCoder);
788
      if (!outStream)
789
        *outBufSize = p->outBuf - outBuf;
790
      return res;
791
    }
792
  }
793
794
  #endif
795
796
797
7.77k
  return Lzma2Enc_EncodeMt1(p,
798
7.77k
      &p->coders[0],
799
7.77k
      outStream, outBuf, outBufSize,
800
7.77k
      inStream, inData, inDataSize,
801
7.77k
      True, /* finished */
802
7.77k
      progress);
803
7.77k
}