Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/Lzma2DecMt.c
4253 views
1
/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
2
2023-04-13 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
// #define SHOW_DEBUG_INFO
7
// #define Z7_ST
8
9
#ifdef SHOW_DEBUG_INFO
10
#include <stdio.h>
11
#endif
12
13
#include "Alloc.h"
14
15
#include "Lzma2Dec.h"
16
#include "Lzma2DecMt.h"
17
18
#ifndef Z7_ST
19
#include "MtDec.h"
20
21
#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
22
#endif
23
24
25
#ifndef Z7_ST
26
#ifdef SHOW_DEBUG_INFO
27
#define PRF(x) x
28
#else
29
#define PRF(x)
30
#endif
31
#define PRF_STR(s) PRF(printf("\n" s "\n");)
32
#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2);)
33
#endif
34
35
36
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)
37
{
38
p->inBufSize_ST = 1 << 20;
39
p->outStep_ST = 1 << 20;
40
41
#ifndef Z7_ST
42
p->numThreads = 1;
43
p->inBufSize_MT = 1 << 18;
44
p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;
45
p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;
46
#endif
47
}
48
49
50
51
#ifndef Z7_ST
52
53
/* ---------- CLzma2DecMtThread ---------- */
54
55
typedef struct
56
{
57
CLzma2Dec dec;
58
Byte dec_created;
59
Byte needInit;
60
61
Byte *outBuf;
62
size_t outBufSize;
63
64
EMtDecParseState state;
65
ELzma2ParseStatus parseStatus;
66
67
size_t inPreSize;
68
size_t outPreSize;
69
70
size_t inCodeSize;
71
size_t outCodeSize;
72
SRes codeRes;
73
74
CAlignOffsetAlloc alloc;
75
76
Byte mtPad[1 << 7];
77
} CLzma2DecMtThread;
78
79
#endif
80
81
82
/* ---------- CLzma2DecMt ---------- */
83
84
struct CLzma2DecMt
85
{
86
// ISzAllocPtr alloc;
87
ISzAllocPtr allocMid;
88
89
CAlignOffsetAlloc alignOffsetAlloc;
90
CLzma2DecMtProps props;
91
Byte prop;
92
93
ISeqInStreamPtr inStream;
94
ISeqOutStreamPtr outStream;
95
ICompressProgressPtr progress;
96
97
BoolInt finishMode;
98
BoolInt outSize_Defined;
99
UInt64 outSize;
100
101
UInt64 outProcessed;
102
UInt64 inProcessed;
103
BoolInt readWasFinished;
104
SRes readRes;
105
106
Byte *inBuf;
107
size_t inBufSize;
108
Byte dec_created;
109
CLzma2Dec dec;
110
111
size_t inPos;
112
size_t inLim;
113
114
#ifndef Z7_ST
115
UInt64 outProcessed_Parse;
116
BoolInt mtc_WasConstructed;
117
CMtDec mtc;
118
CLzma2DecMtThread coders[MTDEC_THREADS_MAX];
119
#endif
120
};
121
122
123
124
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
125
{
126
CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));
127
if (!p)
128
return NULL;
129
130
// p->alloc = alloc;
131
p->allocMid = allocMid;
132
133
AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
134
p->alignOffsetAlloc.numAlignBits = 7;
135
p->alignOffsetAlloc.offset = 0;
136
p->alignOffsetAlloc.baseAlloc = alloc;
137
138
p->inBuf = NULL;
139
p->inBufSize = 0;
140
p->dec_created = False;
141
142
// Lzma2DecMtProps_Init(&p->props);
143
144
#ifndef Z7_ST
145
p->mtc_WasConstructed = False;
146
{
147
unsigned i;
148
for (i = 0; i < MTDEC_THREADS_MAX; i++)
149
{
150
CLzma2DecMtThread *t = &p->coders[i];
151
t->dec_created = False;
152
t->outBuf = NULL;
153
t->outBufSize = 0;
154
}
155
}
156
#endif
157
158
return (CLzma2DecMtHandle)(void *)p;
159
}
160
161
162
#ifndef Z7_ST
163
164
static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)
165
{
166
unsigned i;
167
for (i = 0; i < MTDEC_THREADS_MAX; i++)
168
{
169
CLzma2DecMtThread *t = &p->coders[i];
170
if (t->outBuf)
171
{
172
ISzAlloc_Free(p->allocMid, t->outBuf);
173
t->outBuf = NULL;
174
t->outBufSize = 0;
175
}
176
}
177
}
178
179
#endif
180
181
182
static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)
183
{
184
if (p->dec_created)
185
{
186
Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);
187
p->dec_created = False;
188
}
189
if (p->inBuf)
190
{
191
ISzAlloc_Free(p->allocMid, p->inBuf);
192
p->inBuf = NULL;
193
}
194
p->inBufSize = 0;
195
}
196
197
198
// #define GET_CLzma2DecMt_p CLzma2DecMt *p = (CLzma2DecMt *)(void *)pp;
199
200
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p)
201
{
202
// GET_CLzma2DecMt_p
203
204
Lzma2DecMt_FreeSt(p);
205
206
#ifndef Z7_ST
207
208
if (p->mtc_WasConstructed)
209
{
210
MtDec_Destruct(&p->mtc);
211
p->mtc_WasConstructed = False;
212
}
213
{
214
unsigned i;
215
for (i = 0; i < MTDEC_THREADS_MAX; i++)
216
{
217
CLzma2DecMtThread *t = &p->coders[i];
218
if (t->dec_created)
219
{
220
// we don't need to free dict here
221
Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!
222
t->dec_created = False;
223
}
224
}
225
}
226
Lzma2DecMt_FreeOutBufs(p);
227
228
#endif
229
230
ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p);
231
}
232
233
234
235
#ifndef Z7_ST
236
237
static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
238
{
239
CLzma2DecMt *me = (CLzma2DecMt *)obj;
240
CLzma2DecMtThread *t = &me->coders[coderIndex];
241
242
PRF_STR_INT_2("Parse", coderIndex, cc->srcSize)
243
244
cc->state = MTDEC_PARSE_CONTINUE;
245
246
if (cc->startCall)
247
{
248
if (!t->dec_created)
249
{
250
Lzma2Dec_CONSTRUCT(&t->dec)
251
t->dec_created = True;
252
AlignOffsetAlloc_CreateVTable(&t->alloc);
253
{
254
/* (1 << 12) is expected size of one way in data cache.
255
We optimize alignment for cache line size of 128 bytes and smaller */
256
const unsigned kNumAlignBits = 12;
257
const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */
258
t->alloc.numAlignBits = kNumAlignBits;
259
t->alloc.offset = ((UInt32)coderIndex * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits));
260
t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;
261
}
262
}
263
Lzma2Dec_Init(&t->dec);
264
265
t->inPreSize = 0;
266
t->outPreSize = 0;
267
// t->blockWasFinished = False;
268
// t->finishedWithMark = False;
269
t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
270
t->state = MTDEC_PARSE_CONTINUE;
271
272
t->inCodeSize = 0;
273
t->outCodeSize = 0;
274
t->codeRes = SZ_OK;
275
276
// (cc->srcSize == 0) is allowed
277
}
278
279
{
280
ELzma2ParseStatus status;
281
BoolInt overflow;
282
UInt32 unpackRem = 0;
283
284
int checkFinishBlock = True;
285
size_t limit = me->props.outBlockMax;
286
if (me->outSize_Defined)
287
{
288
UInt64 rem = me->outSize - me->outProcessed_Parse;
289
if (limit >= rem)
290
{
291
limit = (size_t)rem;
292
if (!me->finishMode)
293
checkFinishBlock = False;
294
}
295
}
296
297
// checkFinishBlock = False, if we want to decode partial data
298
// that must be finished at position <= outBlockMax.
299
300
{
301
const size_t srcOrig = cc->srcSize;
302
SizeT srcSize_Point = 0;
303
SizeT dicPos_Point = 0;
304
305
cc->srcSize = 0;
306
overflow = False;
307
308
for (;;)
309
{
310
SizeT srcCur = (SizeT)(srcOrig - cc->srcSize);
311
312
status = Lzma2Dec_Parse(&t->dec,
313
(SizeT)limit - t->dec.decoder.dicPos,
314
cc->src + cc->srcSize, &srcCur,
315
checkFinishBlock);
316
317
cc->srcSize += srcCur;
318
319
if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)
320
{
321
if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)
322
{
323
overflow = True;
324
break;
325
}
326
continue;
327
}
328
329
if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
330
{
331
if (t->dec.decoder.dicPos == 0)
332
continue;
333
// we decode small blocks in one thread
334
if (t->dec.decoder.dicPos >= (1 << 14))
335
break;
336
dicPos_Point = t->dec.decoder.dicPos;
337
srcSize_Point = (SizeT)cc->srcSize;
338
continue;
339
}
340
341
if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock
342
// && limit == t->dec.decoder.dicPos
343
// && limit == me->props.outBlockMax
344
)
345
{
346
overflow = True;
347
break;
348
}
349
350
unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);
351
break;
352
}
353
354
if (dicPos_Point != 0
355
&& (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK
356
&& (int)status != LZMA_STATUS_FINISHED_WITH_MARK
357
&& (int)status != LZMA_STATUS_NOT_SPECIFIED)
358
{
359
// we revert to latest newBlock state
360
status = LZMA2_PARSE_STATUS_NEW_BLOCK;
361
unpackRem = 0;
362
t->dec.decoder.dicPos = dicPos_Point;
363
cc->srcSize = srcSize_Point;
364
overflow = False;
365
}
366
}
367
368
t->inPreSize += cc->srcSize;
369
t->parseStatus = status;
370
371
if (overflow)
372
cc->state = MTDEC_PARSE_OVERFLOW;
373
else
374
{
375
size_t dicPos = t->dec.decoder.dicPos;
376
377
if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)
378
{
379
if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
380
{
381
cc->state = MTDEC_PARSE_NEW;
382
cc->srcSize--; // we don't need control byte of next block
383
t->inPreSize--;
384
}
385
else
386
{
387
cc->state = MTDEC_PARSE_END;
388
if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)
389
{
390
// (status == LZMA_STATUS_NOT_SPECIFIED)
391
// (status == LZMA_STATUS_NOT_FINISHED)
392
if (unpackRem != 0)
393
{
394
/* we also reserve space for max possible number of output bytes of current LZMA chunk */
395
size_t rem = limit - dicPos;
396
if (rem > unpackRem)
397
rem = unpackRem;
398
dicPos += rem;
399
}
400
}
401
}
402
403
me->outProcessed_Parse += dicPos;
404
}
405
406
cc->outPos = dicPos;
407
t->outPreSize = (size_t)dicPos;
408
}
409
410
t->state = cc->state;
411
return;
412
}
413
}
414
415
416
static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)
417
{
418
CLzma2DecMt *me = (CLzma2DecMt *)pp;
419
CLzma2DecMtThread *t = &me->coders[coderIndex];
420
Byte *dest = t->outBuf;
421
422
if (t->inPreSize == 0)
423
{
424
t->codeRes = SZ_ERROR_DATA;
425
return t->codeRes;
426
}
427
428
if (!dest || t->outBufSize < t->outPreSize)
429
{
430
if (dest)
431
{
432
ISzAlloc_Free(me->allocMid, dest);
433
t->outBuf = NULL;
434
t->outBufSize = 0;
435
}
436
437
dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize
438
// + (1 << 28)
439
);
440
// Sleep(200);
441
if (!dest)
442
return SZ_ERROR_MEM;
443
t->outBuf = dest;
444
t->outBufSize = t->outPreSize;
445
}
446
447
t->dec.decoder.dic = dest;
448
t->dec.decoder.dicBufSize = (SizeT)t->outPreSize;
449
450
t->needInit = True;
451
452
return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt
453
}
454
455
456
static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,
457
const Byte *src, size_t srcSize, int srcFinished,
458
// int finished, int blockFinished,
459
UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
460
{
461
CLzma2DecMt *me = (CLzma2DecMt *)pp;
462
CLzma2DecMtThread *t = &me->coders[coderIndex];
463
464
UNUSED_VAR(srcFinished)
465
466
PRF_STR_INT_2("Code", coderIndex, srcSize)
467
468
*inCodePos = t->inCodeSize;
469
*outCodePos = 0;
470
*stop = True;
471
472
if (t->needInit)
473
{
474
Lzma2Dec_Init(&t->dec);
475
t->needInit = False;
476
}
477
478
{
479
ELzmaStatus status;
480
SizeT srcProcessed = (SizeT)srcSize;
481
BoolInt blockWasFinished =
482
((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
483
|| t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);
484
485
SRes res = Lzma2Dec_DecodeToDic(&t->dec,
486
(SizeT)t->outPreSize,
487
src, &srcProcessed,
488
blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,
489
&status);
490
491
t->codeRes = res;
492
493
t->inCodeSize += srcProcessed;
494
*inCodePos = t->inCodeSize;
495
t->outCodeSize = t->dec.decoder.dicPos;
496
*outCodePos = t->dec.decoder.dicPos;
497
498
if (res != SZ_OK)
499
return res;
500
501
if (srcProcessed == srcSize)
502
*stop = False;
503
504
if (blockWasFinished)
505
{
506
if (srcSize != srcProcessed)
507
return SZ_ERROR_FAIL;
508
509
if (t->inPreSize == t->inCodeSize)
510
{
511
if (t->outPreSize != t->outCodeSize)
512
return SZ_ERROR_FAIL;
513
*stop = True;
514
}
515
}
516
else
517
{
518
if (t->outPreSize == t->outCodeSize)
519
*stop = True;
520
}
521
522
return SZ_OK;
523
}
524
}
525
526
527
#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)
528
529
static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
530
BoolInt needWriteToStream,
531
const Byte *src, size_t srcSize, BoolInt isCross,
532
BoolInt *needContinue, BoolInt *canRecode)
533
{
534
CLzma2DecMt *me = (CLzma2DecMt *)pp;
535
const CLzma2DecMtThread *t = &me->coders[coderIndex];
536
size_t size = t->outCodeSize;
537
const Byte *data = t->outBuf;
538
BoolInt needContinue2 = True;
539
540
UNUSED_VAR(src)
541
UNUSED_VAR(srcSize)
542
UNUSED_VAR(isCross)
543
544
PRF_STR_INT_2("Write", coderIndex, srcSize)
545
546
*needContinue = False;
547
*canRecode = True;
548
549
if (
550
// t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
551
t->state == MTDEC_PARSE_OVERFLOW
552
|| t->state == MTDEC_PARSE_END)
553
needContinue2 = False;
554
555
556
if (!needWriteToStream)
557
return SZ_OK;
558
559
me->mtc.inProcessed += t->inCodeSize;
560
561
if (t->codeRes == SZ_OK)
562
if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
563
|| t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
564
if (t->outPreSize != t->outCodeSize
565
|| t->inPreSize != t->inCodeSize)
566
return SZ_ERROR_FAIL;
567
568
*canRecode = False;
569
570
if (me->outStream)
571
{
572
for (;;)
573
{
574
size_t cur = size;
575
size_t written;
576
if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
577
cur = LZMA2DECMT_STREAM_WRITE_STEP;
578
579
written = ISeqOutStream_Write(me->outStream, data, cur);
580
581
me->outProcessed += written;
582
// me->mtc.writtenTotal += written;
583
if (written != cur)
584
return SZ_ERROR_WRITE;
585
data += cur;
586
size -= cur;
587
if (size == 0)
588
{
589
*needContinue = needContinue2;
590
return SZ_OK;
591
}
592
RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0))
593
}
594
}
595
596
return SZ_ERROR_FAIL;
597
/*
598
if (size > me->outBufSize)
599
return SZ_ERROR_OUTPUT_EOF;
600
memcpy(me->outBuf, data, size);
601
me->outBufSize -= size;
602
me->outBuf += size;
603
*needContinue = needContinue2;
604
return SZ_OK;
605
*/
606
}
607
608
#endif
609
610
611
static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
612
{
613
if (!p->dec_created)
614
{
615
Lzma2Dec_CONSTRUCT(&p->dec)
616
p->dec_created = True;
617
}
618
619
RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt))
620
621
if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
622
{
623
ISzAlloc_Free(p->allocMid, p->inBuf);
624
p->inBufSize = 0;
625
p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
626
if (!p->inBuf)
627
return SZ_ERROR_MEM;
628
p->inBufSize = p->props.inBufSize_ST;
629
}
630
631
Lzma2Dec_Init(&p->dec);
632
633
return SZ_OK;
634
}
635
636
637
static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
638
#ifndef Z7_ST
639
, BoolInt tMode
640
#endif
641
)
642
{
643
SizeT wrPos;
644
size_t inPos, inLim;
645
const Byte *inData;
646
UInt64 inPrev, outPrev;
647
648
CLzma2Dec *dec;
649
650
#ifndef Z7_ST
651
if (tMode)
652
{
653
Lzma2DecMt_FreeOutBufs(p);
654
tMode = MtDec_PrepareRead(&p->mtc);
655
}
656
#endif
657
658
RINOK(Lzma2Dec_Prepare_ST(p))
659
660
dec = &p->dec;
661
662
inPrev = p->inProcessed;
663
outPrev = p->outProcessed;
664
665
inPos = 0;
666
inLim = 0;
667
inData = NULL;
668
wrPos = dec->decoder.dicPos;
669
670
for (;;)
671
{
672
SizeT dicPos;
673
SizeT size;
674
ELzmaFinishMode finishMode;
675
SizeT inProcessed;
676
ELzmaStatus status;
677
SRes res;
678
679
SizeT outProcessed;
680
BoolInt outFinished;
681
BoolInt needStop;
682
683
if (inPos == inLim)
684
{
685
#ifndef Z7_ST
686
if (tMode)
687
{
688
inData = MtDec_Read(&p->mtc, &inLim);
689
inPos = 0;
690
if (inData)
691
continue;
692
tMode = False;
693
inLim = 0;
694
}
695
#endif
696
697
if (!p->readWasFinished)
698
{
699
inPos = 0;
700
inLim = p->inBufSize;
701
inData = p->inBuf;
702
p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim);
703
// p->readProcessed += inLim;
704
// inLim -= 5; p->readWasFinished = True; // for test
705
if (inLim == 0 || p->readRes != SZ_OK)
706
p->readWasFinished = True;
707
}
708
}
709
710
dicPos = dec->decoder.dicPos;
711
{
712
SizeT next = dec->decoder.dicBufSize;
713
if (next - wrPos > p->props.outStep_ST)
714
next = wrPos + (SizeT)p->props.outStep_ST;
715
size = next - dicPos;
716
}
717
718
finishMode = LZMA_FINISH_ANY;
719
if (p->outSize_Defined)
720
{
721
const UInt64 rem = p->outSize - p->outProcessed;
722
if (size >= rem)
723
{
724
size = (SizeT)rem;
725
if (p->finishMode)
726
finishMode = LZMA_FINISH_END;
727
}
728
}
729
730
inProcessed = (SizeT)(inLim - inPos);
731
732
res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
733
734
inPos += inProcessed;
735
p->inProcessed += inProcessed;
736
outProcessed = dec->decoder.dicPos - dicPos;
737
p->outProcessed += outProcessed;
738
739
outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
740
741
needStop = (res != SZ_OK
742
|| (inProcessed == 0 && outProcessed == 0)
743
|| status == LZMA_STATUS_FINISHED_WITH_MARK
744
|| (!p->finishMode && outFinished));
745
746
if (needStop || outProcessed >= size)
747
{
748
SRes res2;
749
{
750
size_t writeSize = dec->decoder.dicPos - wrPos;
751
size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
752
res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
753
}
754
755
if (dec->decoder.dicPos == dec->decoder.dicBufSize)
756
dec->decoder.dicPos = 0;
757
wrPos = dec->decoder.dicPos;
758
759
RINOK(res2)
760
761
if (needStop)
762
{
763
if (res != SZ_OK)
764
return res;
765
766
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
767
{
768
if (p->finishMode)
769
{
770
if (p->outSize_Defined && p->outSize != p->outProcessed)
771
return SZ_ERROR_DATA;
772
}
773
return SZ_OK;
774
}
775
776
if (!p->finishMode && outFinished)
777
return SZ_OK;
778
779
if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
780
return SZ_ERROR_INPUT_EOF;
781
782
return SZ_ERROR_DATA;
783
}
784
}
785
786
if (p->progress)
787
{
788
UInt64 inDelta = p->inProcessed - inPrev;
789
UInt64 outDelta = p->outProcessed - outPrev;
790
if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
791
{
792
RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed))
793
inPrev = p->inProcessed;
794
outPrev = p->outProcessed;
795
}
796
}
797
}
798
}
799
800
801
802
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
803
Byte prop,
804
const CLzma2DecMtProps *props,
805
ISeqOutStreamPtr outStream, const UInt64 *outDataSize, int finishMode,
806
// Byte *outBuf, size_t *outBufSize,
807
ISeqInStreamPtr inStream,
808
// const Byte *inData, size_t inDataSize,
809
UInt64 *inProcessed,
810
// UInt64 *outProcessed,
811
int *isMT,
812
ICompressProgressPtr progress)
813
{
814
// GET_CLzma2DecMt_p
815
#ifndef Z7_ST
816
BoolInt tMode;
817
#endif
818
819
*inProcessed = 0;
820
821
if (prop > 40)
822
return SZ_ERROR_UNSUPPORTED;
823
824
p->prop = prop;
825
p->props = *props;
826
827
p->inStream = inStream;
828
p->outStream = outStream;
829
p->progress = progress;
830
831
p->outSize = 0;
832
p->outSize_Defined = False;
833
if (outDataSize)
834
{
835
p->outSize_Defined = True;
836
p->outSize = *outDataSize;
837
}
838
p->finishMode = finishMode;
839
840
p->outProcessed = 0;
841
p->inProcessed = 0;
842
843
p->readWasFinished = False;
844
p->readRes = SZ_OK;
845
846
*isMT = False;
847
848
849
#ifndef Z7_ST
850
851
tMode = False;
852
853
// p->mtc.parseRes = SZ_OK;
854
855
// p->mtc.numFilledThreads = 0;
856
// p->mtc.crossStart = 0;
857
// p->mtc.crossEnd = 0;
858
// p->mtc.allocError_for_Read_BlockIndex = 0;
859
// p->mtc.isAllocError = False;
860
861
if (p->props.numThreads > 1)
862
{
863
IMtDecCallback2 vt;
864
865
Lzma2DecMt_FreeSt(p);
866
867
p->outProcessed_Parse = 0;
868
869
if (!p->mtc_WasConstructed)
870
{
871
p->mtc_WasConstructed = True;
872
MtDec_Construct(&p->mtc);
873
}
874
875
p->mtc.progress = progress;
876
p->mtc.inStream = inStream;
877
878
// p->outBuf = NULL;
879
// p->outBufSize = 0;
880
/*
881
if (!outStream)
882
{
883
// p->outBuf = outBuf;
884
// p->outBufSize = *outBufSize;
885
// *outBufSize = 0;
886
return SZ_ERROR_PARAM;
887
}
888
*/
889
890
// p->mtc.inBlockMax = p->props.inBlockMax;
891
p->mtc.alloc = &p->alignOffsetAlloc.vt;
892
// p->alignOffsetAlloc.baseAlloc;
893
// p->mtc.inData = inData;
894
// p->mtc.inDataSize = inDataSize;
895
p->mtc.mtCallback = &vt;
896
p->mtc.mtCallbackObject = p;
897
898
p->mtc.inBufSize = p->props.inBufSize_MT;
899
900
p->mtc.numThreadsMax = p->props.numThreads;
901
902
*isMT = True;
903
904
vt.Parse = Lzma2DecMt_MtCallback_Parse;
905
vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
906
vt.Code = Lzma2DecMt_MtCallback_Code;
907
vt.Write = Lzma2DecMt_MtCallback_Write;
908
909
{
910
BoolInt needContinue = False;
911
912
SRes res = MtDec_Code(&p->mtc);
913
914
/*
915
if (!outStream)
916
*outBufSize = p->outBuf - outBuf;
917
*/
918
919
*inProcessed = p->mtc.inProcessed;
920
921
needContinue = False;
922
923
if (res == SZ_OK)
924
{
925
if (p->mtc.mtProgress.res != SZ_OK)
926
res = p->mtc.mtProgress.res;
927
else
928
needContinue = p->mtc.needContinue;
929
}
930
931
if (!needContinue)
932
{
933
if (res == SZ_OK)
934
return p->mtc.readRes;
935
return res;
936
}
937
938
tMode = True;
939
p->readRes = p->mtc.readRes;
940
p->readWasFinished = p->mtc.readWasFinished;
941
p->inProcessed = p->mtc.inProcessed;
942
943
PRF_STR("----- decoding ST -----")
944
}
945
}
946
947
#endif
948
949
950
*isMT = False;
951
952
{
953
SRes res = Lzma2Dec_Decode_ST(p
954
#ifndef Z7_ST
955
, tMode
956
#endif
957
);
958
959
*inProcessed = p->inProcessed;
960
961
// res = SZ_OK; // for test
962
if (res == SZ_ERROR_INPUT_EOF)
963
{
964
if (p->readRes != SZ_OK)
965
res = p->readRes;
966
}
967
else if (res == SZ_OK && p->readRes != SZ_OK)
968
res = p->readRes;
969
970
/*
971
#ifndef Z7_ST
972
if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
973
res = p->mtc.parseRes;
974
#endif
975
*/
976
977
return res;
978
}
979
}
980
981
982
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
983
984
SRes Lzma2DecMt_Init(CLzma2DecMtHandle p,
985
Byte prop,
986
const CLzma2DecMtProps *props,
987
const UInt64 *outDataSize, int finishMode,
988
ISeqInStreamPtr inStream)
989
{
990
// GET_CLzma2DecMt_p
991
992
if (prop > 40)
993
return SZ_ERROR_UNSUPPORTED;
994
995
p->prop = prop;
996
p->props = *props;
997
998
p->inStream = inStream;
999
1000
p->outSize = 0;
1001
p->outSize_Defined = False;
1002
if (outDataSize)
1003
{
1004
p->outSize_Defined = True;
1005
p->outSize = *outDataSize;
1006
}
1007
p->finishMode = finishMode;
1008
1009
p->outProcessed = 0;
1010
p->inProcessed = 0;
1011
1012
p->inPos = 0;
1013
p->inLim = 0;
1014
1015
return Lzma2Dec_Prepare_ST(p);
1016
}
1017
1018
1019
SRes Lzma2DecMt_Read(CLzma2DecMtHandle p,
1020
Byte *data, size_t *outSize,
1021
UInt64 *inStreamProcessed)
1022
{
1023
// GET_CLzma2DecMt_p
1024
ELzmaFinishMode finishMode;
1025
SRes readRes;
1026
size_t size = *outSize;
1027
1028
*outSize = 0;
1029
*inStreamProcessed = 0;
1030
1031
finishMode = LZMA_FINISH_ANY;
1032
if (p->outSize_Defined)
1033
{
1034
const UInt64 rem = p->outSize - p->outProcessed;
1035
if (size >= rem)
1036
{
1037
size = (size_t)rem;
1038
if (p->finishMode)
1039
finishMode = LZMA_FINISH_END;
1040
}
1041
}
1042
1043
readRes = SZ_OK;
1044
1045
for (;;)
1046
{
1047
SizeT inCur;
1048
SizeT outCur;
1049
ELzmaStatus status;
1050
SRes res;
1051
1052
if (p->inPos == p->inLim && readRes == SZ_OK)
1053
{
1054
p->inPos = 0;
1055
p->inLim = p->props.inBufSize_ST;
1056
readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
1057
}
1058
1059
inCur = (SizeT)(p->inLim - p->inPos);
1060
outCur = (SizeT)size;
1061
1062
res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
1063
p->inBuf + p->inPos, &inCur, finishMode, &status);
1064
1065
p->inPos += inCur;
1066
p->inProcessed += inCur;
1067
*inStreamProcessed += inCur;
1068
p->outProcessed += outCur;
1069
*outSize += outCur;
1070
size -= outCur;
1071
data += outCur;
1072
1073
if (res != 0)
1074
return res;
1075
1076
/*
1077
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
1078
return readRes;
1079
1080
if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
1081
{
1082
if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
1083
return SZ_ERROR_DATA;
1084
return readRes;
1085
}
1086
*/
1087
1088
if (inCur == 0 && outCur == 0)
1089
return readRes;
1090
}
1091
}
1092
1093
#undef PRF
1094
#undef PRF_STR
1095
#undef PRF_STR_INT_2
1096
1097