Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/Lzma2Enc.c
4253 views
1
/* Lzma2Enc.c -- LZMA2 Encoder
2
2023-04-13 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
#include <string.h>
7
8
/* #define Z7_ST */
9
10
#include "Lzma2Enc.h"
11
12
#ifndef Z7_ST
13
#include "MtCoder.h"
14
#else
15
#define MTCODER_THREADS_MAX 1
16
#endif
17
18
#define LZMA2_CONTROL_LZMA (1 << 7)
19
#define LZMA2_CONTROL_COPY_NO_RESET 2
20
#define LZMA2_CONTROL_COPY_RESET_DIC 1
21
#define LZMA2_CONTROL_EOF 0
22
23
#define LZMA2_LCLP_MAX 4
24
25
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
26
27
#define LZMA2_PACK_SIZE_MAX (1 << 16)
28
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
29
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
30
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
31
32
#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
ISeqInStreamPtr realStream;
44
UInt64 limit;
45
UInt64 processed;
46
int finished;
47
} CLimitedSeqInStream;
48
49
static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
50
{
51
p->limit = (UInt64)(Int64)-1;
52
p->processed = 0;
53
p->finished = 0;
54
}
55
56
static SRes LimitedSeqInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size)
57
{
58
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream)
59
size_t size2 = *size;
60
SRes res = SZ_OK;
61
62
if (p->limit != (UInt64)(Int64)-1)
63
{
64
const UInt64 rem = p->limit - p->processed;
65
if (size2 > rem)
66
size2 = (size_t)rem;
67
}
68
if (size2 != 0)
69
{
70
res = ISeqInStream_Read(p->realStream, data, &size2);
71
p->finished = (size2 == 0 ? 1 : 0);
72
p->processed += size2;
73
}
74
*size = size2;
75
return res;
76
}
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
{
94
if (!p->propsAreSet)
95
{
96
SizeT propsSize = LZMA_PROPS_SIZE;
97
Byte propsEncoded[LZMA_PROPS_SIZE];
98
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps))
99
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize))
100
p->propsByte = propsEncoded[0];
101
p->propsAreSet = True;
102
}
103
return SZ_OK;
104
}
105
106
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
107
{
108
p->srcPos = 0;
109
p->needInitState = True;
110
p->needInitProp = True;
111
}
112
113
114
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,
115
ISzAllocPtr alloc, ISzAllocPtr allocBig);
116
SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,
117
UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
118
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,
119
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
120
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);
121
void LzmaEnc_Finish(CLzmaEncHandle p);
122
void LzmaEnc_SaveState(CLzmaEncHandle p);
123
void LzmaEnc_RestoreState(CLzmaEncHandle p);
124
125
/*
126
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p);
127
*/
128
129
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
130
size_t *packSizeRes, ISeqOutStreamPtr outStream)
131
{
132
size_t packSizeLimit = *packSizeRes;
133
size_t packSize = packSizeLimit;
134
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
135
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
136
BoolInt useCopyBlock;
137
SRes res;
138
139
*packSizeRes = 0;
140
if (packSize < lzHeaderSize)
141
return SZ_ERROR_OUTPUT_EOF;
142
packSize -= lzHeaderSize;
143
144
LzmaEnc_SaveState(p->enc);
145
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
146
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
147
148
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
149
150
if (unpackSize == 0)
151
return res;
152
153
if (res == SZ_OK)
154
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
155
else
156
{
157
if (res != SZ_ERROR_OUTPUT_EOF)
158
return res;
159
res = SZ_OK;
160
useCopyBlock = True;
161
}
162
163
if (useCopyBlock)
164
{
165
size_t destPos = 0;
166
PRF(printf("################# COPY "));
167
168
while (unpackSize > 0)
169
{
170
const UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
171
if (packSizeLimit - destPos < u + 3)
172
return SZ_ERROR_OUTPUT_EOF;
173
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
174
outBuf[destPos++] = (Byte)((u - 1) >> 8);
175
outBuf[destPos++] = (Byte)(u - 1);
176
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
177
unpackSize -= u;
178
destPos += u;
179
p->srcPos += u;
180
181
if (outStream)
182
{
183
*packSizeRes += destPos;
184
if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
185
return SZ_ERROR_WRITE;
186
destPos = 0;
187
}
188
else
189
*packSizeRes = destPos;
190
/* needInitState = True; */
191
}
192
193
LzmaEnc_RestoreState(p->enc);
194
return SZ_OK;
195
}
196
197
{
198
size_t destPos = 0;
199
const UInt32 u = unpackSize - 1;
200
const UInt32 pm = (UInt32)(packSize - 1);
201
const unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
202
203
PRF(printf(" "));
204
205
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
206
outBuf[destPos++] = (Byte)(u >> 8);
207
outBuf[destPos++] = (Byte)u;
208
outBuf[destPos++] = (Byte)(pm >> 8);
209
outBuf[destPos++] = (Byte)pm;
210
211
if (p->needInitProp)
212
outBuf[destPos++] = p->propsByte;
213
214
p->needInitProp = False;
215
p->needInitState = False;
216
destPos += packSize;
217
p->srcPos += unpackSize;
218
219
if (outStream)
220
if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
221
return SZ_ERROR_WRITE;
222
223
*packSizeRes = destPos;
224
return SZ_OK;
225
}
226
}
227
228
229
/* ---------- Lzma2 Props ---------- */
230
231
void Lzma2EncProps_Init(CLzma2EncProps *p)
232
{
233
LzmaEncProps_Init(&p->lzmaProps);
234
p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO;
235
p->numBlockThreads_Reduced = -1;
236
p->numBlockThreads_Max = -1;
237
p->numTotalThreads = -1;
238
}
239
240
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
241
{
242
UInt64 fileSize;
243
int t1, t1n, t2, t2r, t3;
244
{
245
CLzmaEncProps lzmaProps = p->lzmaProps;
246
LzmaEncProps_Normalize(&lzmaProps);
247
t1n = lzmaProps.numThreads;
248
}
249
250
t1 = p->lzmaProps.numThreads;
251
t2 = p->numBlockThreads_Max;
252
t3 = p->numTotalThreads;
253
254
if (t2 > MTCODER_THREADS_MAX)
255
t2 = MTCODER_THREADS_MAX;
256
257
if (t3 <= 0)
258
{
259
if (t2 <= 0)
260
t2 = 1;
261
t3 = t1n * t2;
262
}
263
else if (t2 <= 0)
264
{
265
t2 = t3 / t1n;
266
if (t2 == 0)
267
{
268
t1 = 1;
269
t2 = t3;
270
}
271
if (t2 > MTCODER_THREADS_MAX)
272
t2 = MTCODER_THREADS_MAX;
273
}
274
else if (t1 <= 0)
275
{
276
t1 = t3 / t2;
277
if (t1 == 0)
278
t1 = 1;
279
}
280
else
281
t3 = t1n * t2;
282
283
p->lzmaProps.numThreads = t1;
284
285
t2r = t2;
286
287
fileSize = p->lzmaProps.reduceSize;
288
289
if ( p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
290
&& p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO
291
&& (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
292
p->lzmaProps.reduceSize = p->blockSize;
293
294
LzmaEncProps_Normalize(&p->lzmaProps);
295
296
p->lzmaProps.reduceSize = fileSize;
297
298
t1 = p->lzmaProps.numThreads;
299
300
if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)
301
{
302
t2r = t2 = 1;
303
t3 = t1;
304
}
305
else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1)
306
{
307
/* if there is no block multi-threading, we use SOLID block */
308
p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;
309
}
310
else
311
{
312
if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)
313
{
314
const UInt32 kMinSize = (UInt32)1 << 20;
315
const UInt32 kMaxSize = (UInt32)1 << 28;
316
const UInt32 dictSize = p->lzmaProps.dictSize;
317
UInt64 blockSize = (UInt64)dictSize << 2;
318
if (blockSize < kMinSize) blockSize = kMinSize;
319
if (blockSize > kMaxSize) blockSize = kMaxSize;
320
if (blockSize < dictSize) blockSize = dictSize;
321
blockSize += (kMinSize - 1);
322
blockSize &= ~(UInt64)(kMinSize - 1);
323
p->blockSize = blockSize;
324
}
325
326
if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
327
{
328
UInt64 numBlocks = fileSize / p->blockSize;
329
if (numBlocks * p->blockSize != fileSize)
330
numBlocks++;
331
if (numBlocks < (unsigned)t2)
332
{
333
t2r = (int)numBlocks;
334
if (t2r == 0)
335
t2r = 1;
336
t3 = t1 * t2r;
337
}
338
}
339
}
340
341
p->numBlockThreads_Max = t2;
342
p->numBlockThreads_Reduced = t2r;
343
p->numTotalThreads = t3;
344
}
345
346
347
static SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize)
348
{
349
return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
350
}
351
352
353
/* ---------- Lzma2 ---------- */
354
355
struct CLzma2Enc
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 Z7_ST
369
370
ISeqOutStreamPtr 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
383
384
385
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
386
{
387
CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
388
if (!p)
389
return NULL;
390
Lzma2EncProps_Init(&p->props);
391
Lzma2EncProps_Normalize(&p->props);
392
p->expectedDataSize = (UInt64)(Int64)-1;
393
p->tempBufLzma = NULL;
394
p->alloc = alloc;
395
p->allocBig = allocBig;
396
{
397
unsigned i;
398
for (i = 0; i < MTCODER_THREADS_MAX; i++)
399
p->coders[i].enc = NULL;
400
}
401
402
#ifndef Z7_ST
403
p->mtCoder_WasConstructed = False;
404
{
405
unsigned i;
406
for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
407
p->outBufs[i] = NULL;
408
p->outBufSize = 0;
409
}
410
#endif
411
412
return (CLzma2EncHandle)p;
413
}
414
415
416
#ifndef Z7_ST
417
418
static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
419
{
420
unsigned i;
421
for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
422
if (p->outBufs[i])
423
{
424
ISzAlloc_Free(p->alloc, p->outBufs[i]);
425
p->outBufs[i] = NULL;
426
}
427
p->outBufSize = 0;
428
}
429
430
#endif
431
432
// #define GET_CLzma2Enc_p CLzma2Enc *p = (CLzma2Enc *)(void *)p;
433
434
void Lzma2Enc_Destroy(CLzma2EncHandle p)
435
{
436
// GET_CLzma2Enc_p
437
unsigned i;
438
for (i = 0; i < MTCODER_THREADS_MAX; i++)
439
{
440
CLzma2EncInt *t = &p->coders[i];
441
if (t->enc)
442
{
443
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
444
t->enc = NULL;
445
}
446
}
447
448
449
#ifndef Z7_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
ISzAlloc_Free(p->alloc, p->tempBufLzma);
459
p->tempBufLzma = NULL;
460
461
ISzAlloc_Free(p->alloc, p);
462
}
463
464
465
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props)
466
{
467
// GET_CLzma2Enc_p
468
CLzmaEncProps lzmaProps = props->lzmaProps;
469
LzmaEncProps_Normalize(&lzmaProps);
470
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
471
return SZ_ERROR_PARAM;
472
p->props = *props;
473
Lzma2EncProps_Normalize(&p->props);
474
return SZ_OK;
475
}
476
477
478
void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize)
479
{
480
// GET_CLzma2Enc_p
481
p->expectedDataSize = expectedDataSiize;
482
}
483
484
485
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p)
486
{
487
// GET_CLzma2Enc_p
488
unsigned i;
489
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
490
for (i = 0; i < 40; i++)
491
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
492
break;
493
return (Byte)i;
494
}
495
496
497
static SRes Lzma2Enc_EncodeMt1(
498
CLzma2Enc *me,
499
CLzma2EncInt *p,
500
ISeqOutStreamPtr outStream,
501
Byte *outBuf, size_t *outBufSize,
502
ISeqInStreamPtr inStream,
503
const Byte *inData, size_t inDataSize,
504
int finished,
505
ICompressProgressPtr progress)
506
{
507
UInt64 unpackTotal = 0;
508
UInt64 packTotal = 0;
509
size_t outLim = 0;
510
CLimitedSeqInStream limitedInStream;
511
512
if (outBuf)
513
{
514
outLim = *outBufSize;
515
*outBufSize = 0;
516
}
517
518
if (!p->enc)
519
{
520
p->propsAreSet = False;
521
p->enc = LzmaEnc_Create(me->alloc);
522
if (!p->enc)
523
return SZ_ERROR_MEM;
524
}
525
526
limitedInStream.realStream = inStream;
527
if (inStream)
528
{
529
limitedInStream.vt.Read = LimitedSeqInStream_Read;
530
}
531
532
if (!outBuf)
533
{
534
// outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
535
if (!me->tempBufLzma)
536
{
537
me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
538
if (!me->tempBufLzma)
539
return SZ_ERROR_MEM;
540
}
541
}
542
543
RINOK(Lzma2EncInt_InitStream(p, &me->props))
544
545
for (;;)
546
{
547
SRes res = SZ_OK;
548
SizeT inSizeCur = 0;
549
550
Lzma2EncInt_InitBlock(p);
551
552
LimitedSeqInStream_Init(&limitedInStream);
553
limitedInStream.limit = me->props.blockSize;
554
555
if (inStream)
556
{
557
UInt64 expected = (UInt64)(Int64)-1;
558
// inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
559
if (me->expectedDataSize != (UInt64)(Int64)-1
560
&& me->expectedDataSize >= unpackTotal)
561
expected = me->expectedDataSize - unpackTotal;
562
if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
563
&& expected > me->props.blockSize)
564
expected = (size_t)me->props.blockSize;
565
566
LzmaEnc_SetDataSize(p->enc, expected);
567
568
RINOK(LzmaEnc_PrepareForLzma2(p->enc,
569
&limitedInStream.vt,
570
LZMA2_KEEP_WINDOW_SIZE,
571
me->alloc,
572
me->allocBig))
573
}
574
else
575
{
576
inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal);
577
if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
578
&& inSizeCur > me->props.blockSize)
579
inSizeCur = (SizeT)(size_t)me->props.blockSize;
580
581
// LzmaEnc_SetDataSize(p->enc, inSizeCur);
582
583
RINOK(LzmaEnc_MemPrepare(p->enc,
584
inData + (size_t)unpackTotal, inSizeCur,
585
LZMA2_KEEP_WINDOW_SIZE,
586
me->alloc,
587
me->allocBig))
588
}
589
590
for (;;)
591
{
592
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
593
if (outBuf)
594
packSize = outLim - (size_t)packTotal;
595
596
res = Lzma2EncInt_EncodeSubblock(p,
597
outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
598
outBuf ? NULL : outStream);
599
600
if (res != SZ_OK)
601
break;
602
603
packTotal += packSize;
604
if (outBuf)
605
*outBufSize = (size_t)packTotal;
606
607
res = Progress(progress, unpackTotal + p->srcPos, packTotal);
608
if (res != SZ_OK)
609
break;
610
611
/*
612
if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
613
break;
614
*/
615
616
if (packSize == 0)
617
break;
618
}
619
620
LzmaEnc_Finish(p->enc);
621
622
unpackTotal += p->srcPos;
623
624
RINOK(res)
625
626
if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
627
return SZ_ERROR_FAIL;
628
629
if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
630
{
631
if (finished)
632
{
633
if (outBuf)
634
{
635
const size_t destPos = *outBufSize;
636
if (destPos >= outLim)
637
return SZ_ERROR_OUTPUT_EOF;
638
outBuf[destPos] = LZMA2_CONTROL_EOF; // 0
639
*outBufSize = destPos + 1;
640
}
641
else
642
{
643
const Byte b = LZMA2_CONTROL_EOF; // 0;
644
if (ISeqOutStream_Write(outStream, &b, 1) != 1)
645
return SZ_ERROR_WRITE;
646
}
647
}
648
return SZ_OK;
649
}
650
}
651
}
652
653
654
655
#ifndef Z7_ST
656
657
static SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex,
658
const Byte *src, size_t srcSize, int finished)
659
{
660
CLzma2Enc *me = (CLzma2Enc *)p;
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 *p, unsigned outBufIndex)
696
{
697
CLzma2Enc *me = (CLzma2Enc *)p;
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 p,
717
ISeqOutStreamPtr outStream,
718
Byte *outBuf, size_t *outBufSize,
719
ISeqInStreamPtr inStream,
720
const Byte *inData, size_t inDataSize,
721
ICompressProgressPtr progress)
722
{
723
// GET_CLzma2Enc_p
724
725
if (inStream && inData)
726
return SZ_ERROR_PARAM;
727
728
if (outStream && outBuf)
729
return SZ_ERROR_PARAM;
730
731
{
732
unsigned i;
733
for (i = 0; i < MTCODER_THREADS_MAX; i++)
734
p->coders[i].propsAreSet = False;
735
}
736
737
#ifndef Z7_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
const 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 = (unsigned)p->props.numBlockThreads_Max;
784
p->mtCoder.expectedDataSize = p->expectedDataSize;
785
786
{
787
const SRes res = MtCoder_Code(&p->mtCoder);
788
if (!outStream)
789
*outBufSize = (size_t)(p->outBuf - outBuf);
790
return res;
791
}
792
}
793
794
#endif
795
796
797
return Lzma2Enc_EncodeMt1(p,
798
&p->coders[0],
799
outStream, outBuf, outBufSize,
800
inStream, inData, inDataSize,
801
True, /* finished */
802
progress);
803
}
804
805
#undef PRF
806
807