Coverage Report

Created: 2024-07-27 06:12

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