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
151k
#define MTCODER__THREADS_MAX 1
16
#endif
17
18
14.2k
#define LZMA2_CONTROL_LZMA (1 << 7)
19
2.77k
#define LZMA2_CONTROL_COPY_NO_RESET 2
20
3.78k
#define LZMA2_CONTROL_COPY_RESET_DIC 1
21
#define LZMA2_CONTROL_EOF 0
22
23
16.0k
#define LZMA2_LCLP_MAX 4
24
25
400k
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
26
27
43.3k
#define LZMA2_PACK_SIZE_MAX (1 << 16)
28
6.56k
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
29
36.8k
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
30
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
31
32
36.8k
#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
16.0k
{
51
16.0k
  p->limit = (UInt64)(Int64)-1;
52
16.0k
  p->processed = 0;
53
16.0k
  p->finished = 0;
54
16.0k
}
55
56
static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
57
33.8k
{
58
33.8k
  CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);
59
33.8k
  size_t size2 = *size;
60
33.8k
  SRes res = SZ_OK;
61
  
62
33.8k
  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
33.8k
  if (size2 != 0)
69
33.8k
  {
70
33.8k
    res = ISeqInStream_Read(p->realStream, data, &size2);
71
33.8k
    p->finished = (size2 == 0 ? 1 : 0);
72
33.8k
    p->processed += size2;
73
33.8k
  }
74
33.8k
  *size = size2;
75
33.8k
  return res;
76
33.8k
}
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
16.0k
{
94
16.0k
  if (!p->propsAreSet)
95
16.0k
  {
96
16.0k
    SizeT propsSize = LZMA_PROPS_SIZE;
97
16.0k
    Byte propsEncoded[LZMA_PROPS_SIZE];
98
16.0k
    RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
99
16.0k
    RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
100
16.0k
    p->propsByte = propsEncoded[0];
101
16.0k
    p->propsAreSet = True;
102
16.0k
  }
103
16.0k
  return SZ_OK;
104
16.0k
}
105
106
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
107
16.0k
{
108
16.0k
  p->srcPos = 0;
109
16.0k
  p->needInitState = True;
110
16.0k
  p->needInitProp = True;
111
16.0k
}
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
36.8k
{
132
36.8k
  size_t packSizeLimit = *packSizeRes;
133
36.8k
  size_t packSize = packSizeLimit;
134
36.8k
  UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
135
36.8k
  unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
136
36.8k
  BoolInt useCopyBlock;
137
36.8k
  SRes res;
138
139
36.8k
  *packSizeRes = 0;
140
36.8k
  if (packSize < lzHeaderSize)
141
0
    return SZ_ERROR_OUTPUT_EOF;
142
36.8k
  packSize -= lzHeaderSize;
143
  
144
36.8k
  LzmaEnc_SaveState(p->enc);
145
36.8k
  res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
146
36.8k
      outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
147
  
148
36.8k
  PRF(printf("\npackSize = %7d unpackSize = %7d  ", packSize, unpackSize));
149
150
36.8k
  if (unpackSize == 0)
151
16.0k
    return res;
152
153
20.8k
  if (res == SZ_OK)
154
20.8k
    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
20.8k
  if (useCopyBlock)
164
6.56k
  {
165
6.56k
    size_t destPos = 0;
166
6.56k
    PRF(printf("################# COPY           "));
167
168
13.1k
    while (unpackSize > 0)
169
6.56k
    {
170
6.56k
      UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
171
6.56k
      if (packSizeLimit - destPos < u + 3)
172
0
        return SZ_ERROR_OUTPUT_EOF;
173
6.56k
      outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
174
6.56k
      outBuf[destPos++] = (Byte)((u - 1) >> 8);
175
6.56k
      outBuf[destPos++] = (Byte)(u - 1);
176
6.56k
      memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
177
6.56k
      unpackSize -= u;
178
6.56k
      destPos += u;
179
6.56k
      p->srcPos += u;
180
      
181
6.56k
      if (outStream)
182
6.56k
      {
183
6.56k
        *packSizeRes += destPos;
184
6.56k
        if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
185
0
          return SZ_ERROR_WRITE;
186
6.56k
        destPos = 0;
187
6.56k
      }
188
0
      else
189
0
        *packSizeRes = destPos;
190
      /* needInitState = True; */
191
6.56k
    }
192
    
193
6.56k
    LzmaEnc_RestoreState(p->enc);
194
6.56k
    return SZ_OK;
195
6.56k
  }
196
197
14.2k
  {
198
14.2k
    size_t destPos = 0;
199
14.2k
    UInt32 u = unpackSize - 1;
200
14.2k
    UInt32 pm = (UInt32)(packSize - 1);
201
14.2k
    unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
202
203
14.2k
    PRF(printf("               "));
204
205
14.2k
    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
206
14.2k
    outBuf[destPos++] = (Byte)(u >> 8);
207
14.2k
    outBuf[destPos++] = (Byte)u;
208
14.2k
    outBuf[destPos++] = (Byte)(pm >> 8);
209
14.2k
    outBuf[destPos++] = (Byte)pm;
210
    
211
14.2k
    if (p->needInitProp)
212
12.3k
      outBuf[destPos++] = p->propsByte;
213
    
214
14.2k
    p->needInitProp = False;
215
14.2k
    p->needInitState = False;
216
14.2k
    destPos += packSize;
217
14.2k
    p->srcPos += unpackSize;
218
219
14.2k
    if (outStream)
220
14.2k
      if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
221
0
        return SZ_ERROR_WRITE;
222
    
223
14.2k
    *packSizeRes = destPos;
224
14.2k
    return SZ_OK;
225
14.2k
  }
226
14.2k
}
227
228
229
/* ---------- Lzma2 Props ---------- */
230
231
void Lzma2EncProps_Init(CLzma2EncProps *p)
232
39.8k
{
233
39.8k
  LzmaEncProps_Init(&p->lzmaProps);
234
39.8k
  p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;
235
39.8k
  p->numBlockThreads_Reduced = -1;
236
39.8k
  p->numBlockThreads_Max = -1;
237
39.8k
  p->numTotalThreads = -1;
238
39.8k
}
239
240
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
241
55.8k
{
242
55.8k
  UInt64 fileSize;
243
55.8k
  int t1, t1n, t2, t2r, t3;
244
55.8k
  {
245
55.8k
    CLzmaEncProps lzmaProps = p->lzmaProps;
246
55.8k
    LzmaEncProps_Normalize(&lzmaProps);
247
55.8k
    t1n = lzmaProps.numThreads;
248
55.8k
  }
249
250
55.8k
  t1 = p->lzmaProps.numThreads;
251
55.8k
  t2 = p->numBlockThreads_Max;
252
55.8k
  t3 = p->numTotalThreads;
253
254
55.8k
  if (t2 > MTCODER__THREADS_MAX)
255
0
    t2 = MTCODER__THREADS_MAX;
256
257
55.8k
  if (t3 <= 0)
258
47.6k
  {
259
47.6k
    if (t2 <= 0)
260
39.8k
      t2 = 1;
261
47.6k
    t3 = t1n * t2;
262
47.6k
  }
263
8.23k
  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
8.23k
  else if (t1 <= 0)
275
0
  {
276
0
    t1 = t3 / t2;
277
0
    if (t1 == 0)
278
0
      t1 = 1;
279
0
  }
280
8.23k
  else
281
8.23k
    t3 = t1n * t2;
282
283
55.8k
  p->lzmaProps.numThreads = t1;
284
285
55.8k
  t2r = t2;
286
287
55.8k
  fileSize = p->lzmaProps.reduceSize;
288
289
55.8k
  if (   p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
290
55.8k
      && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
291
55.8k
      && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
292
0
    p->lzmaProps.reduceSize = p->blockSize;
293
294
55.8k
  LzmaEncProps_Normalize(&p->lzmaProps);
295
296
55.8k
  p->lzmaProps.reduceSize = fileSize;
297
298
55.8k
  t1 = p->lzmaProps.numThreads;
299
300
55.8k
  if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
301
16.0k
  {
302
16.0k
    t2r = t2 = 1;
303
16.0k
    t3 = t1;
304
16.0k
  }
305
39.8k
  else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)
306
39.8k
  {
307
    /* if there is no block multi-threading, we use SOLID block */
308
39.8k
    p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
309
39.8k
  }
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
55.8k
  p->numBlockThreads_Max = t2;
342
55.8k
  p->numBlockThreads_Reduced = t2r;
343
55.8k
  p->numTotalThreads = t3;
344
55.8k
}
345
346
347
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
348
36.8k
{
349
36.8k
  return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
350
36.8k
}
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
16.0k
{
388
16.0k
  CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
389
16.0k
  if (!p)
390
0
    return NULL;
391
16.0k
  Lzma2EncProps_Init(&p->props);
392
16.0k
  Lzma2EncProps_Normalize(&p->props);
393
16.0k
  p->expectedDataSize = (UInt64)(Int64)-1;
394
16.0k
  p->tempBufLzma = NULL;
395
16.0k
  p->alloc = alloc;
396
16.0k
  p->allocBig = allocBig;
397
16.0k
  {
398
16.0k
    unsigned i;
399
32.0k
    for (i = 0; i < MTCODER__THREADS_MAX; i++)
400
16.0k
      p->coders[i].enc = NULL;
401
16.0k
  }
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
16.0k
  return p;
414
16.0k
}
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
16.0k
{
436
16.0k
  CLzma2Enc *p = (CLzma2Enc *)pp;
437
16.0k
  unsigned i;
438
32.0k
  for (i = 0; i < MTCODER__THREADS_MAX; i++)
439
16.0k
  {
440
16.0k
    CLzma2EncInt *t = &p->coders[i];
441
16.0k
    if (t->enc)
442
16.0k
    {
443
16.0k
      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
444
16.0k
      t->enc = NULL;
445
16.0k
    }
446
16.0k
  }
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
16.0k
  ISzAlloc_Free(p->alloc, p->tempBufLzma);
459
16.0k
  p->tempBufLzma = NULL;
460
461
16.0k
  ISzAlloc_Free(p->alloc, pp);
462
16.0k
}
463
464
465
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
466
16.0k
{
467
16.0k
  CLzma2Enc *p = (CLzma2Enc *)pp;
468
16.0k
  CLzmaEncProps lzmaProps = props->lzmaProps;
469
16.0k
  LzmaEncProps_Normalize(&lzmaProps);
470
16.0k
  if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
471
14
    return SZ_ERROR_PARAM;
472
16.0k
  p->props = *props;
473
16.0k
  Lzma2EncProps_Normalize(&p->props);
474
16.0k
  return SZ_OK;
475
16.0k
}
476
477
478
void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
479
8.23k
{
480
8.23k
  CLzma2Enc *p = (CLzma2Enc *)pp;
481
8.23k
  p->expectedDataSize = expectedDataSiize;
482
8.23k
}
483
484
485
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
486
16.0k
{
487
16.0k
  CLzma2Enc *p = (CLzma2Enc *)pp;
488
16.0k
  unsigned i;
489
16.0k
  UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
490
400k
  for (i = 0; i < 40; i++)
491
400k
    if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
492
16.0k
      break;
493
16.0k
  return (Byte)i;
494
16.0k
}
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
16.0k
{
507
16.0k
  UInt64 unpackTotal = 0;
508
16.0k
  UInt64 packTotal = 0;
509
16.0k
  size_t outLim = 0;
510
16.0k
  CLimitedSeqInStream limitedInStream;
511
512
16.0k
  if (outBuf)
513
0
  {
514
0
    outLim = *outBufSize;
515
0
    *outBufSize = 0;
516
0
  }
517
518
16.0k
  if (!p->enc)
519
16.0k
  {
520
16.0k
    p->propsAreSet = False;
521
16.0k
    p->enc = LzmaEnc_Create(me->alloc);
522
16.0k
    if (!p->enc)
523
0
      return SZ_ERROR_MEM;
524
16.0k
  }
525
526
16.0k
  limitedInStream.realStream = inStream;
527
16.0k
  if (inStream)
528
16.0k
  {
529
16.0k
    limitedInStream.vt.Read = LimitedSeqInStream_Read;
530
16.0k
  }
531
  
532
16.0k
  if (!outBuf)
533
16.0k
  {
534
    // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
535
16.0k
    if (!me->tempBufLzma)
536
16.0k
    {
537
16.0k
      me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
538
16.0k
      if (!me->tempBufLzma)
539
0
        return SZ_ERROR_MEM;
540
16.0k
    }
541
16.0k
  }
542
543
16.0k
  RINOK(Lzma2EncInt_InitStream(p, &me->props));
544
545
16.0k
  for (;;)
546
16.0k
  {
547
16.0k
    SRes res = SZ_OK;
548
16.0k
    size_t inSizeCur = 0;
549
550
16.0k
    Lzma2EncInt_InitBlock(p);
551
    
552
16.0k
    LimitedSeqInStream_Init(&limitedInStream);
553
16.0k
    limitedInStream.limit = me->props.blockSize;
554
555
16.0k
    if (inStream)
556
16.0k
    {
557
16.0k
      UInt64 expected = (UInt64)(Int64)-1;
558
      // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
559
16.0k
      if (me->expectedDataSize != (UInt64)(Int64)-1
560
16.0k
          && me->expectedDataSize >= unpackTotal)
561
8.23k
        expected = me->expectedDataSize - unpackTotal;
562
16.0k
      if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
563
16.0k
          && expected > me->props.blockSize)
564
0
        expected = (size_t)me->props.blockSize;
565
566
16.0k
      LzmaEnc_SetDataSize(p->enc, expected);
567
568
16.0k
      RINOK(LzmaEnc_PrepareForLzma2(p->enc,
569
16.0k
          &limitedInStream.vt,
570
16.0k
          LZMA2_KEEP_WINDOW_SIZE,
571
16.0k
          me->alloc,
572
16.0k
          me->allocBig));
573
16.0k
    }
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
16.0k
    for (;;)
591
36.8k
    {
592
36.8k
      size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
593
36.8k
      if (outBuf)
594
0
        packSize = outLim - (size_t)packTotal;
595
      
596
36.8k
      res = Lzma2EncInt_EncodeSubblock(p,
597
36.8k
          outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
598
36.8k
          outBuf ? NULL : outStream);
599
      
600
36.8k
      if (res != SZ_OK)
601
0
        break;
602
603
36.8k
      packTotal += packSize;
604
36.8k
      if (outBuf)
605
0
        *outBufSize = (size_t)packTotal;
606
      
607
36.8k
      res = Progress(progress, unpackTotal + p->srcPos, packTotal);
608
36.8k
      if (res != SZ_OK)
609
0
        break;
610
611
      /*
612
      if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
613
        break;
614
      */
615
616
36.8k
      if (packSize == 0)
617
16.0k
        break;
618
36.8k
    }
619
    
620
16.0k
    LzmaEnc_Finish(p->enc);
621
    
622
16.0k
    unpackTotal += p->srcPos;
623
    
624
16.0k
    RINOK(res);
625
626
16.0k
    if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
627
0
      return SZ_ERROR_FAIL;
628
    
629
16.0k
    if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
630
16.0k
    {
631
16.0k
      if (finished)
632
16.0k
      {
633
16.0k
        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
16.0k
        else
642
16.0k
        {
643
16.0k
          Byte b = 0;
644
16.0k
          if (ISeqOutStream_Write(outStream, &b, 1) != 1)
645
0
            return SZ_ERROR_WRITE;
646
16.0k
        }
647
16.0k
      }
648
16.0k
      return SZ_OK;
649
16.0k
    }
650
16.0k
  }
651
16.0k
}
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
16.0k
{
723
16.0k
  CLzma2Enc *p = (CLzma2Enc *)pp;
724
725
16.0k
  if (inStream && inData)
726
0
    return SZ_ERROR_PARAM;
727
728
16.0k
  if (outStream && outBuf)
729
0
    return SZ_ERROR_PARAM;
730
731
16.0k
  {
732
16.0k
    unsigned i;
733
32.0k
    for (i = 0; i < MTCODER__THREADS_MAX; i++)
734
16.0k
      p->coders[i].propsAreSet = False;
735
16.0k
  }
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
16.0k
  return Lzma2Enc_EncodeMt1(p,
798
16.0k
      &p->coders[0],
799
16.0k
      outStream, outBuf, outBufSize,
800
16.0k
      inStream, inData, inDataSize,
801
16.0k
      True, /* finished */
802
16.0k
      progress);
803
16.0k
}