Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/XzDec.c
4253 views
1
/* XzDec.c -- Xz Decode
2
2024-03-01 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
// #include <stdio.h>
7
8
// #define XZ_DUMP
9
10
/* #define XZ_DUMP */
11
12
#ifdef XZ_DUMP
13
#include <stdio.h>
14
#endif
15
16
// #define SHOW_DEBUG_INFO
17
18
#ifdef SHOW_DEBUG_INFO
19
#include <stdio.h>
20
#endif
21
22
#ifdef SHOW_DEBUG_INFO
23
#define PRF(x) x
24
#else
25
#define PRF(x)
26
#endif
27
28
#define PRF_STR(s) PRF(printf("\n" s "\n"))
29
#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
30
31
#include <stdlib.h>
32
#include <string.h>
33
34
#include "7zCrc.h"
35
#include "Alloc.h"
36
#include "Bra.h"
37
#include "CpuArch.h"
38
#include "Delta.h"
39
#include "Lzma2Dec.h"
40
41
// #define USE_SUBBLOCK
42
43
#ifdef USE_SUBBLOCK
44
#include "Bcj3Dec.c"
45
#include "SbDec.h"
46
#endif
47
48
#include "Xz.h"
49
50
#define XZ_CHECK_SIZE_MAX 64
51
52
#define CODER_BUF_SIZE ((size_t)1 << 17)
53
54
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
55
{
56
unsigned i, limit;
57
*value = 0;
58
limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
59
60
for (i = 0; i < limit;)
61
{
62
Byte b = p[i];
63
*value |= (UInt64)(b & 0x7F) << (7 * i++);
64
if ((b & 0x80) == 0)
65
return (b == 0 && i != 1) ? 0 : i;
66
}
67
return 0;
68
}
69
70
71
/* ---------- XzBcFilterState ---------- */
72
73
#define BRA_BUF_SIZE (1 << 14)
74
75
typedef struct
76
{
77
size_t bufPos;
78
size_t bufConv;
79
size_t bufTotal;
80
Byte *buf; // must be aligned for 4 bytes
81
Xz_Func_BcFilterStateBase_Filter filter_func;
82
// int encodeMode;
83
CXzBcFilterStateBase base;
84
// Byte buf[BRA_BUF_SIZE];
85
} CXzBcFilterState;
86
87
88
static void XzBcFilterState_Free(void *pp, ISzAllocPtr alloc)
89
{
90
if (pp)
91
{
92
CXzBcFilterState *p = ((CXzBcFilterState *)pp);
93
ISzAlloc_Free(alloc, p->buf);
94
ISzAlloc_Free(alloc, pp);
95
}
96
}
97
98
99
static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
100
{
101
CXzBcFilterStateBase *p = &((CXzBcFilterState *)pp)->base;
102
UNUSED_VAR(alloc)
103
p->ip = 0;
104
if (p->methodId == XZ_ID_Delta)
105
{
106
if (propSize != 1)
107
return SZ_ERROR_UNSUPPORTED;
108
p->delta = (UInt32)props[0] + 1;
109
}
110
else
111
{
112
if (propSize == 4)
113
{
114
const UInt32 v = GetUi32(props);
115
switch (p->methodId)
116
{
117
case XZ_ID_PPC:
118
case XZ_ID_ARM:
119
case XZ_ID_SPARC:
120
case XZ_ID_ARM64:
121
if (v & 3)
122
return SZ_ERROR_UNSUPPORTED;
123
break;
124
case XZ_ID_ARMT:
125
case XZ_ID_RISCV:
126
if (v & 1)
127
return SZ_ERROR_UNSUPPORTED;
128
break;
129
case XZ_ID_IA64:
130
if (v & 0xf)
131
return SZ_ERROR_UNSUPPORTED;
132
break;
133
default: break;
134
}
135
p->ip = v;
136
}
137
else if (propSize != 0)
138
return SZ_ERROR_UNSUPPORTED;
139
}
140
return SZ_OK;
141
}
142
143
144
static void XzBcFilterState_Init(void *pp)
145
{
146
CXzBcFilterState *p = ((CXzBcFilterState *)pp);
147
p->bufPos = p->bufConv = p->bufTotal = 0;
148
p->base.X86_State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;
149
if (p->base.methodId == XZ_ID_Delta)
150
Delta_Init(p->base.delta_State);
151
}
152
153
154
static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] =
155
{
156
Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC),
157
Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64),
158
Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM),
159
Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT),
160
Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC),
161
Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64),
162
Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV)
163
};
164
165
static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size)
166
{
167
switch (p->methodId)
168
{
169
case XZ_ID_Delta:
170
Delta_Decode(p->delta_State, p->delta, data, size);
171
break;
172
case XZ_ID_X86:
173
size = (SizeT)(z7_BranchConvSt_X86_Dec(data, size, p->ip, &p->X86_State) - data);
174
break;
175
default:
176
if (p->methodId >= XZ_ID_PPC)
177
{
178
const UInt32 i = p->methodId - XZ_ID_PPC;
179
if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Dec))
180
size = (SizeT)(g_Funcs_BranchConv_RISC_Dec[i](data, size, p->ip) - data);
181
}
182
break;
183
}
184
p->ip += (UInt32)size;
185
return size;
186
}
187
188
189
static SizeT XzBcFilterState_Filter(void *pp, Byte *data, SizeT size)
190
{
191
CXzBcFilterState *p = ((CXzBcFilterState *)pp);
192
return p->filter_func(&p->base, data, size);
193
}
194
195
196
static SRes XzBcFilterState_Code2(void *pp,
197
Byte *dest, SizeT *destLen,
198
const Byte *src, SizeT *srcLen, int srcWasFinished,
199
ECoderFinishMode finishMode,
200
// int *wasFinished
201
ECoderStatus *status)
202
{
203
CXzBcFilterState *p = ((CXzBcFilterState *)pp);
204
SizeT destRem = *destLen;
205
SizeT srcRem = *srcLen;
206
UNUSED_VAR(finishMode)
207
208
*destLen = 0;
209
*srcLen = 0;
210
// *wasFinished = False;
211
*status = CODER_STATUS_NOT_FINISHED;
212
213
while (destRem != 0)
214
{
215
{
216
size_t size = p->bufConv - p->bufPos;
217
if (size)
218
{
219
if (size > destRem)
220
size = destRem;
221
memcpy(dest, p->buf + p->bufPos, size);
222
p->bufPos += size;
223
*destLen += size;
224
dest += size;
225
destRem -= size;
226
continue;
227
}
228
}
229
230
p->bufTotal -= p->bufPos;
231
memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
232
p->bufPos = 0;
233
p->bufConv = 0;
234
{
235
size_t size = BRA_BUF_SIZE - p->bufTotal;
236
if (size > srcRem)
237
size = srcRem;
238
memcpy(p->buf + p->bufTotal, src, size);
239
*srcLen += size;
240
src += size;
241
srcRem -= size;
242
p->bufTotal += size;
243
}
244
if (p->bufTotal == 0)
245
break;
246
247
p->bufConv = p->filter_func(&p->base, p->buf, p->bufTotal);
248
249
if (p->bufConv == 0)
250
{
251
if (!srcWasFinished)
252
break;
253
p->bufConv = p->bufTotal;
254
}
255
}
256
257
if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
258
{
259
*status = CODER_STATUS_FINISHED_WITH_MARK;
260
// *wasFinished = 1;
261
}
262
263
return SZ_OK;
264
}
265
266
267
#define XZ_IS_SUPPORTED_FILTER_ID(id) \
268
((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV)
269
270
SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
271
Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc)
272
{
273
CXzBcFilterState *decoder;
274
if (!XZ_IS_SUPPORTED_FILTER_ID(id))
275
return SZ_ERROR_UNSUPPORTED;
276
decoder = (CXzBcFilterState *)p->p;
277
if (!decoder)
278
{
279
decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState));
280
if (!decoder)
281
return SZ_ERROR_MEM;
282
decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE);
283
if (!decoder->buf)
284
{
285
ISzAlloc_Free(alloc, decoder);
286
return SZ_ERROR_MEM;
287
}
288
p->p = decoder;
289
p->Free = XzBcFilterState_Free;
290
p->SetProps = XzBcFilterState_SetProps;
291
p->Init = XzBcFilterState_Init;
292
p->Code2 = XzBcFilterState_Code2;
293
p->Filter = XzBcFilterState_Filter;
294
decoder->filter_func = func;
295
}
296
decoder->base.methodId = (UInt32)id;
297
// decoder->encodeMode = encodeMode;
298
return SZ_OK;
299
}
300
301
302
303
/* ---------- SbState ---------- */
304
305
#ifdef USE_SUBBLOCK
306
307
static void SbState_Free(void *pp, ISzAllocPtr alloc)
308
{
309
CSbDec *p = (CSbDec *)pp;
310
SbDec_Free(p);
311
ISzAlloc_Free(alloc, pp);
312
}
313
314
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
315
{
316
UNUSED_VAR(pp)
317
UNUSED_VAR(props)
318
UNUSED_VAR(alloc)
319
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
320
}
321
322
static void SbState_Init(void *pp)
323
{
324
SbDec_Init((CSbDec *)pp);
325
}
326
327
static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
328
int srcWasFinished, ECoderFinishMode finishMode,
329
// int *wasFinished
330
ECoderStatus *status)
331
{
332
CSbDec *p = (CSbDec *)pp;
333
SRes res;
334
UNUSED_VAR(srcWasFinished)
335
p->dest = dest;
336
p->destLen = *destLen;
337
p->src = src;
338
p->srcLen = *srcLen;
339
p->finish = finishMode; /* change it */
340
res = SbDec_Decode((CSbDec *)pp);
341
*destLen -= p->destLen;
342
*srcLen -= p->srcLen;
343
// *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
344
*status = (*destLen == 0 && *srcLen == 0) ?
345
CODER_STATUS_FINISHED_WITH_MARK :
346
CODER_STATUS_NOT_FINISHED;
347
return res;
348
}
349
350
static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
351
{
352
CSbDec *decoder = (CSbDec *)p->p;
353
if (!decoder)
354
{
355
decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
356
if (!decoder)
357
return SZ_ERROR_MEM;
358
p->p = decoder;
359
p->Free = SbState_Free;
360
p->SetProps = SbState_SetProps;
361
p->Init = SbState_Init;
362
p->Code2 = SbState_Code2;
363
p->Filter = NULL;
364
}
365
SbDec_Construct(decoder);
366
SbDec_SetAlloc(decoder, alloc);
367
return SZ_OK;
368
}
369
370
#endif
371
372
373
374
/* ---------- Lzma2 ---------- */
375
376
typedef struct
377
{
378
CLzma2Dec decoder;
379
BoolInt outBufMode;
380
} CLzma2Dec_Spec;
381
382
383
static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
384
{
385
CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
386
if (p->outBufMode)
387
Lzma2Dec_FreeProbs(&p->decoder, alloc);
388
else
389
Lzma2Dec_Free(&p->decoder, alloc);
390
ISzAlloc_Free(alloc, pp);
391
}
392
393
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
394
{
395
if (propSize != 1)
396
return SZ_ERROR_UNSUPPORTED;
397
{
398
CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
399
if (p->outBufMode)
400
return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
401
else
402
return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
403
}
404
}
405
406
static void Lzma2State_Init(void *pp)
407
{
408
Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
409
}
410
411
412
/*
413
if (outBufMode), then (dest) is not used. Use NULL.
414
Data is unpacked to (spec->decoder.decoder.dic) output buffer.
415
*/
416
417
static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
418
int srcWasFinished, ECoderFinishMode finishMode,
419
// int *wasFinished,
420
ECoderStatus *status)
421
{
422
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
423
ELzmaStatus status2;
424
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
425
SRes res;
426
UNUSED_VAR(srcWasFinished)
427
if (spec->outBufMode)
428
{
429
SizeT dicPos = spec->decoder.decoder.dicPos;
430
SizeT dicLimit = dicPos + *destLen;
431
res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
432
*destLen = spec->decoder.decoder.dicPos - dicPos;
433
}
434
else
435
res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
436
// *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
437
// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
438
*status = (ECoderStatus)status2;
439
return res;
440
}
441
442
443
static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
444
{
445
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
446
if (!spec)
447
{
448
spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
449
if (!spec)
450
return SZ_ERROR_MEM;
451
p->p = spec;
452
p->Free = Lzma2State_Free;
453
p->SetProps = Lzma2State_SetProps;
454
p->Init = Lzma2State_Init;
455
p->Code2 = Lzma2State_Code2;
456
p->Filter = NULL;
457
Lzma2Dec_CONSTRUCT(&spec->decoder)
458
}
459
spec->outBufMode = False;
460
if (outBuf)
461
{
462
spec->outBufMode = True;
463
spec->decoder.decoder.dic = outBuf;
464
spec->decoder.decoder.dicBufSize = outBufSize;
465
}
466
return SZ_OK;
467
}
468
469
470
static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
471
{
472
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
473
if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
474
return SZ_ERROR_FAIL;
475
if (outBuf)
476
{
477
spec->decoder.decoder.dic = outBuf;
478
spec->decoder.decoder.dicBufSize = outBufSize;
479
}
480
return SZ_OK;
481
}
482
483
484
485
static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
486
{
487
unsigned i;
488
p->alloc = alloc;
489
p->buf = NULL;
490
p->numCoders = 0;
491
492
p->outBufSize = 0;
493
p->outBuf = NULL;
494
// p->SingleBufMode = False;
495
496
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
497
p->coders[i].p = NULL;
498
}
499
500
501
static void MixCoder_Free(CMixCoder *p)
502
{
503
unsigned i;
504
p->numCoders = 0;
505
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
506
{
507
IStateCoder *sc = &p->coders[i];
508
if (sc->p)
509
{
510
sc->Free(sc->p, p->alloc);
511
sc->p = NULL;
512
}
513
}
514
if (p->buf)
515
{
516
ISzAlloc_Free(p->alloc, p->buf);
517
p->buf = NULL; /* 9.31: the BUG was fixed */
518
}
519
}
520
521
static void MixCoder_Init(CMixCoder *p)
522
{
523
unsigned i;
524
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
525
{
526
p->size[i] = 0;
527
p->pos[i] = 0;
528
p->finished[i] = 0;
529
}
530
for (i = 0; i < p->numCoders; i++)
531
{
532
IStateCoder *coder = &p->coders[i];
533
coder->Init(coder->p);
534
p->results[i] = SZ_OK;
535
}
536
p->outWritten = 0;
537
p->wasFinished = False;
538
p->res = SZ_OK;
539
p->status = CODER_STATUS_NOT_SPECIFIED;
540
}
541
542
543
static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
544
{
545
IStateCoder *sc = &p->coders[coderIndex];
546
p->ids[coderIndex] = methodId;
547
if (methodId == XZ_ID_LZMA2)
548
return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
549
#ifdef USE_SUBBLOCK
550
if (methodId == XZ_ID_Subblock)
551
return SbState_SetFromMethod(sc, p->alloc);
552
#endif
553
if (coderIndex == 0)
554
return SZ_ERROR_UNSUPPORTED;
555
return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId,
556
XzBcFilterStateBase_Filter_Dec, p->alloc);
557
}
558
559
560
static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
561
{
562
IStateCoder *sc = &p->coders[coderIndex];
563
if (methodId == XZ_ID_LZMA2)
564
return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
565
return SZ_ERROR_UNSUPPORTED;
566
}
567
568
569
570
/*
571
if (destFinish) - then unpack data block is finished at (*destLen) position,
572
and we can return data that were not processed by filter
573
574
output (status) can be :
575
CODER_STATUS_NOT_FINISHED
576
CODER_STATUS_FINISHED_WITH_MARK
577
CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
578
*/
579
580
static SRes MixCoder_Code(CMixCoder *p,
581
Byte *dest, SizeT *destLen, int destFinish,
582
const Byte *src, SizeT *srcLen, int srcWasFinished,
583
ECoderFinishMode finishMode)
584
{
585
SizeT destLenOrig = *destLen;
586
SizeT srcLenOrig = *srcLen;
587
588
*destLen = 0;
589
*srcLen = 0;
590
591
if (p->wasFinished)
592
return p->res;
593
594
p->status = CODER_STATUS_NOT_FINISHED;
595
596
// if (p->SingleBufMode)
597
if (p->outBuf)
598
{
599
SRes res;
600
SizeT destLen2, srcLen2;
601
int wasFinished;
602
603
PRF_STR("------- MixCoder Single ----------")
604
605
srcLen2 = srcLenOrig;
606
destLen2 = destLenOrig;
607
608
{
609
IStateCoder *coder = &p->coders[0];
610
res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
611
// &wasFinished,
612
&p->status);
613
wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
614
}
615
616
p->res = res;
617
618
/*
619
if (wasFinished)
620
p->status = CODER_STATUS_FINISHED_WITH_MARK;
621
else
622
{
623
if (res == SZ_OK)
624
if (destLen2 != destLenOrig)
625
p->status = CODER_STATUS_NEEDS_MORE_INPUT;
626
}
627
*/
628
629
630
*srcLen = srcLen2;
631
src += srcLen2;
632
p->outWritten += destLen2;
633
634
if (res != SZ_OK || srcWasFinished || wasFinished)
635
p->wasFinished = True;
636
637
if (p->numCoders == 1)
638
*destLen = destLen2;
639
else if (p->wasFinished)
640
{
641
unsigned i;
642
size_t processed = p->outWritten;
643
644
for (i = 1; i < p->numCoders; i++)
645
{
646
IStateCoder *coder = &p->coders[i];
647
processed = coder->Filter(coder->p, p->outBuf, processed);
648
if (wasFinished || (destFinish && p->outWritten == destLenOrig))
649
processed = p->outWritten;
650
PRF_STR_INT("filter", i)
651
}
652
*destLen = processed;
653
}
654
return res;
655
}
656
657
PRF_STR("standard mix")
658
659
if (p->numCoders != 1)
660
{
661
if (!p->buf)
662
{
663
p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
664
if (!p->buf)
665
return SZ_ERROR_MEM;
666
}
667
668
finishMode = CODER_FINISH_ANY;
669
}
670
671
for (;;)
672
{
673
BoolInt processed = False;
674
BoolInt allFinished = True;
675
SRes resMain = SZ_OK;
676
unsigned i;
677
678
p->status = CODER_STATUS_NOT_FINISHED;
679
/*
680
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
681
break;
682
*/
683
684
for (i = 0; i < p->numCoders; i++)
685
{
686
SRes res;
687
IStateCoder *coder = &p->coders[i];
688
Byte *dest2;
689
SizeT destLen2, srcLen2; // destLen2_Orig;
690
const Byte *src2;
691
int srcFinished2;
692
int encodingWasFinished;
693
ECoderStatus status2;
694
695
if (i == 0)
696
{
697
src2 = src;
698
srcLen2 = srcLenOrig - *srcLen;
699
srcFinished2 = srcWasFinished;
700
}
701
else
702
{
703
size_t k = i - 1;
704
src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
705
srcLen2 = p->size[k] - p->pos[k];
706
srcFinished2 = p->finished[k];
707
}
708
709
if (i == p->numCoders - 1)
710
{
711
dest2 = dest;
712
destLen2 = destLenOrig - *destLen;
713
}
714
else
715
{
716
if (p->pos[i] != p->size[i])
717
continue;
718
dest2 = p->buf + (CODER_BUF_SIZE * i);
719
destLen2 = CODER_BUF_SIZE;
720
}
721
722
// destLen2_Orig = destLen2;
723
724
if (p->results[i] != SZ_OK)
725
{
726
if (resMain == SZ_OK)
727
resMain = p->results[i];
728
continue;
729
}
730
731
res = coder->Code2(coder->p,
732
dest2, &destLen2,
733
src2, &srcLen2, srcFinished2,
734
finishMode,
735
// &encodingWasFinished,
736
&status2);
737
738
if (res != SZ_OK)
739
{
740
p->results[i] = res;
741
if (resMain == SZ_OK)
742
resMain = res;
743
}
744
745
encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
746
747
if (!encodingWasFinished)
748
{
749
allFinished = False;
750
if (p->numCoders == 1 && res == SZ_OK)
751
p->status = status2;
752
}
753
754
if (i == 0)
755
{
756
*srcLen += srcLen2;
757
src += srcLen2;
758
}
759
else
760
p->pos[(size_t)i - 1] += srcLen2;
761
762
if (i == p->numCoders - 1)
763
{
764
*destLen += destLen2;
765
dest += destLen2;
766
}
767
else
768
{
769
p->size[i] = destLen2;
770
p->pos[i] = 0;
771
p->finished[i] = encodingWasFinished;
772
}
773
774
if (destLen2 != 0 || srcLen2 != 0)
775
processed = True;
776
}
777
778
if (!processed)
779
{
780
if (allFinished)
781
p->status = CODER_STATUS_FINISHED_WITH_MARK;
782
return resMain;
783
}
784
}
785
}
786
787
788
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
789
{
790
*p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
791
if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
792
GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
793
return SZ_ERROR_NO_ARCHIVE;
794
return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
795
}
796
797
static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
798
{
799
return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
800
&& GetUi32(buf) == CrcCalc(buf + 4, 6)
801
&& flags == GetBe16(buf + 8)
802
&& buf[10] == XZ_FOOTER_SIG_0
803
&& buf[11] == XZ_FOOTER_SIG_1;
804
}
805
806
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
807
{ const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
808
if (s == 0) return SZ_ERROR_ARCHIVE; \
809
pos += s; }
810
811
812
static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
813
{
814
const unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
815
unsigned i;
816
{
817
const CXzFilter *f = &p->filters[numFilters];
818
if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
819
return False;
820
}
821
822
for (i = 0; i < numFilters; i++)
823
{
824
const CXzFilter *f = &p->filters[i];
825
if (f->id == XZ_ID_Delta)
826
{
827
if (f->propsSize != 1)
828
return False;
829
}
830
else if (!XZ_IS_SUPPORTED_FILTER_ID(f->id)
831
|| (f->propsSize != 0 && f->propsSize != 4))
832
return False;
833
}
834
return True;
835
}
836
837
838
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
839
{
840
unsigned pos;
841
unsigned numFilters, i;
842
unsigned headerSize = (unsigned)header[0] << 2;
843
844
/* (headerSize != 0) : another code checks */
845
846
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
847
return SZ_ERROR_ARCHIVE;
848
849
pos = 1;
850
p->flags = header[pos++];
851
852
p->packSize = (UInt64)(Int64)-1;
853
if (XzBlock_HasPackSize(p))
854
{
855
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize)
856
if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
857
return SZ_ERROR_ARCHIVE;
858
}
859
860
p->unpackSize = (UInt64)(Int64)-1;
861
if (XzBlock_HasUnpackSize(p))
862
{
863
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize)
864
}
865
866
numFilters = XzBlock_GetNumFilters(p);
867
for (i = 0; i < numFilters; i++)
868
{
869
CXzFilter *filter = p->filters + i;
870
UInt64 size;
871
READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id)
872
READ_VARINT_AND_CHECK(header, pos, headerSize, &size)
873
if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
874
return SZ_ERROR_ARCHIVE;
875
filter->propsSize = (UInt32)size;
876
memcpy(filter->props, header + pos, (size_t)size);
877
pos += (unsigned)size;
878
879
#ifdef XZ_DUMP
880
printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
881
{
882
unsigned i;
883
for (i = 0; i < size; i++)
884
printf(" %2X", filter->props[i]);
885
}
886
#endif
887
}
888
889
if (XzBlock_HasUnsupportedFlags(p))
890
return SZ_ERROR_UNSUPPORTED;
891
892
while (pos < headerSize)
893
if (header[pos++] != 0)
894
return SZ_ERROR_ARCHIVE;
895
return SZ_OK;
896
}
897
898
899
900
901
static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
902
{
903
unsigned i;
904
BoolInt needReInit = True;
905
unsigned numFilters = XzBlock_GetNumFilters(block);
906
907
if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
908
{
909
needReInit = False;
910
for (i = 0; i < numFilters; i++)
911
if (p->ids[i] != block->filters[numFilters - 1 - i].id)
912
{
913
needReInit = True;
914
break;
915
}
916
}
917
918
// p->SingleBufMode = (outBuf != NULL);
919
p->outBuf = outBuf;
920
p->outBufSize = outBufSize;
921
922
// p->SingleBufMode = False;
923
// outBuf = NULL;
924
925
if (needReInit)
926
{
927
MixCoder_Free(p);
928
for (i = 0; i < numFilters; i++)
929
{
930
RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize))
931
}
932
p->numCoders = numFilters;
933
}
934
else
935
{
936
RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize))
937
}
938
939
for (i = 0; i < numFilters; i++)
940
{
941
const CXzFilter *f = &block->filters[numFilters - 1 - i];
942
IStateCoder *sc = &p->coders[i];
943
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc))
944
}
945
946
MixCoder_Init(p);
947
return SZ_OK;
948
}
949
950
951
952
void XzUnpacker_Init(CXzUnpacker *p)
953
{
954
p->state = XZ_STATE_STREAM_HEADER;
955
p->pos = 0;
956
p->numStartedStreams = 0;
957
p->numFinishedStreams = 0;
958
p->numTotalBlocks = 0;
959
p->padSize = 0;
960
p->decodeOnlyOneBlock = 0;
961
962
p->parseMode = False;
963
p->decodeToStreamSignature = False;
964
965
// p->outBuf = NULL;
966
// p->outBufSize = 0;
967
p->outDataWritten = 0;
968
}
969
970
971
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
972
{
973
p->outBuf = outBuf;
974
p->outBufSize = outBufSize;
975
}
976
977
978
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
979
{
980
MixCoder_Construct(&p->decoder, alloc);
981
p->outBuf = NULL;
982
p->outBufSize = 0;
983
XzUnpacker_Init(p);
984
}
985
986
987
void XzUnpacker_Free(CXzUnpacker *p)
988
{
989
MixCoder_Free(&p->decoder);
990
}
991
992
993
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
994
{
995
p->indexSize = 0;
996
p->numBlocks = 0;
997
Sha256_Init(&p->sha);
998
p->state = XZ_STATE_BLOCK_HEADER;
999
p->pos = 0;
1000
p->decodeOnlyOneBlock = 1;
1001
}
1002
1003
1004
static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
1005
{
1006
Byte temp[32];
1007
unsigned num = Xz_WriteVarInt(temp, packSize);
1008
num += Xz_WriteVarInt(temp + num, unpackSize);
1009
Sha256_Update(&p->sha, temp, num);
1010
p->indexSize += num;
1011
p->numBlocks++;
1012
}
1013
1014
1015
1016
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1017
const Byte *src, SizeT *srcLen, int srcFinished,
1018
ECoderFinishMode finishMode, ECoderStatus *status)
1019
{
1020
SizeT destLenOrig = *destLen;
1021
SizeT srcLenOrig = *srcLen;
1022
*destLen = 0;
1023
*srcLen = 0;
1024
*status = CODER_STATUS_NOT_SPECIFIED;
1025
1026
for (;;)
1027
{
1028
SizeT srcRem;
1029
1030
if (p->state == XZ_STATE_BLOCK)
1031
{
1032
SizeT destLen2 = destLenOrig - *destLen;
1033
SizeT srcLen2 = srcLenOrig - *srcLen;
1034
SRes res;
1035
1036
ECoderFinishMode finishMode2 = finishMode;
1037
BoolInt srcFinished2 = (BoolInt)srcFinished;
1038
BoolInt destFinish = False;
1039
1040
if (p->block.packSize != (UInt64)(Int64)-1)
1041
{
1042
UInt64 rem = p->block.packSize - p->packSize;
1043
if (srcLen2 >= rem)
1044
{
1045
srcFinished2 = True;
1046
srcLen2 = (SizeT)rem;
1047
}
1048
if (rem == 0 && p->block.unpackSize == p->unpackSize)
1049
return SZ_ERROR_DATA;
1050
}
1051
1052
if (p->block.unpackSize != (UInt64)(Int64)-1)
1053
{
1054
UInt64 rem = p->block.unpackSize - p->unpackSize;
1055
if (destLen2 >= rem)
1056
{
1057
destFinish = True;
1058
finishMode2 = CODER_FINISH_END;
1059
destLen2 = (SizeT)rem;
1060
}
1061
}
1062
1063
/*
1064
if (srcLen2 == 0 && destLen2 == 0)
1065
{
1066
*status = CODER_STATUS_NOT_FINISHED;
1067
return SZ_OK;
1068
}
1069
*/
1070
1071
{
1072
res = MixCoder_Code(&p->decoder,
1073
(p->outBuf ? NULL : dest), &destLen2, destFinish,
1074
src, &srcLen2, srcFinished2,
1075
finishMode2);
1076
1077
*status = p->decoder.status;
1078
XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1079
if (!p->outBuf)
1080
dest += destLen2;
1081
p->outDataWritten += destLen2;
1082
}
1083
1084
(*srcLen) += srcLen2;
1085
src += srcLen2;
1086
p->packSize += srcLen2;
1087
(*destLen) += destLen2;
1088
p->unpackSize += destLen2;
1089
1090
RINOK(res)
1091
1092
if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1093
{
1094
if (p->block.packSize == p->packSize
1095
&& *status == CODER_STATUS_NEEDS_MORE_INPUT)
1096
{
1097
PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT")
1098
*status = CODER_STATUS_NOT_SPECIFIED;
1099
return SZ_ERROR_DATA;
1100
}
1101
1102
return SZ_OK;
1103
}
1104
{
1105
XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1106
p->state = XZ_STATE_BLOCK_FOOTER;
1107
p->pos = 0;
1108
p->alignPos = 0;
1109
*status = CODER_STATUS_NOT_SPECIFIED;
1110
1111
if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1112
|| (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1113
{
1114
PRF_STR("ERROR: block.size mismatch")
1115
return SZ_ERROR_DATA;
1116
}
1117
}
1118
// continue;
1119
}
1120
1121
srcRem = srcLenOrig - *srcLen;
1122
1123
// XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1124
if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1125
{
1126
*status = CODER_STATUS_NEEDS_MORE_INPUT;
1127
return SZ_OK;
1128
}
1129
1130
switch ((int)p->state)
1131
{
1132
case XZ_STATE_STREAM_HEADER:
1133
{
1134
if (p->pos < XZ_STREAM_HEADER_SIZE)
1135
{
1136
if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1137
return SZ_ERROR_NO_ARCHIVE;
1138
if (p->decodeToStreamSignature)
1139
return SZ_OK;
1140
p->buf[p->pos++] = *src++;
1141
(*srcLen)++;
1142
}
1143
else
1144
{
1145
RINOK(Xz_ParseHeader(&p->streamFlags, p->buf))
1146
p->numStartedStreams++;
1147
p->indexSize = 0;
1148
p->numBlocks = 0;
1149
Sha256_Init(&p->sha);
1150
p->state = XZ_STATE_BLOCK_HEADER;
1151
p->pos = 0;
1152
}
1153
break;
1154
}
1155
1156
case XZ_STATE_BLOCK_HEADER:
1157
{
1158
if (p->pos == 0)
1159
{
1160
p->buf[p->pos++] = *src++;
1161
(*srcLen)++;
1162
if (p->buf[0] == 0)
1163
{
1164
if (p->decodeOnlyOneBlock)
1165
return SZ_ERROR_DATA;
1166
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1167
p->indexPos = p->indexPreSize;
1168
p->indexSize += p->indexPreSize;
1169
Sha256_Final(&p->sha, p->shaDigest);
1170
Sha256_Init(&p->sha);
1171
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1172
p->state = XZ_STATE_STREAM_INDEX;
1173
break;
1174
}
1175
p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4;
1176
break;
1177
}
1178
1179
if (p->pos != p->blockHeaderSize)
1180
{
1181
unsigned cur = p->blockHeaderSize - p->pos;
1182
if (cur > srcRem)
1183
cur = (unsigned)srcRem;
1184
memcpy(p->buf + p->pos, src, cur);
1185
p->pos += cur;
1186
(*srcLen) += cur;
1187
src += cur;
1188
}
1189
else
1190
{
1191
RINOK(XzBlock_Parse(&p->block, p->buf))
1192
if (!XzBlock_AreSupportedFilters(&p->block))
1193
return SZ_ERROR_UNSUPPORTED;
1194
p->numTotalBlocks++;
1195
p->state = XZ_STATE_BLOCK;
1196
p->packSize = 0;
1197
p->unpackSize = 0;
1198
XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1199
if (p->parseMode)
1200
{
1201
p->headerParsedOk = True;
1202
return SZ_OK;
1203
}
1204
RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize))
1205
}
1206
break;
1207
}
1208
1209
case XZ_STATE_BLOCK_FOOTER:
1210
{
1211
if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1212
{
1213
if (srcRem == 0)
1214
{
1215
*status = CODER_STATUS_NEEDS_MORE_INPUT;
1216
return SZ_OK;
1217
}
1218
(*srcLen)++;
1219
p->alignPos++;
1220
if (*src++ != 0)
1221
return SZ_ERROR_CRC;
1222
}
1223
else
1224
{
1225
const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags);
1226
unsigned cur = checkSize - p->pos;
1227
if (cur != 0)
1228
{
1229
if (srcRem == 0)
1230
{
1231
*status = CODER_STATUS_NEEDS_MORE_INPUT;
1232
return SZ_OK;
1233
}
1234
if (cur > srcRem)
1235
cur = (unsigned)srcRem;
1236
memcpy(p->buf + p->pos, src, cur);
1237
p->pos += cur;
1238
(*srcLen) += cur;
1239
src += cur;
1240
if (checkSize != p->pos)
1241
break;
1242
}
1243
{
1244
Byte digest[XZ_CHECK_SIZE_MAX];
1245
p->state = XZ_STATE_BLOCK_HEADER;
1246
p->pos = 0;
1247
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1248
return SZ_ERROR_CRC;
1249
if (p->decodeOnlyOneBlock)
1250
{
1251
*status = CODER_STATUS_FINISHED_WITH_MARK;
1252
return SZ_OK;
1253
}
1254
}
1255
}
1256
break;
1257
}
1258
1259
case XZ_STATE_STREAM_INDEX:
1260
{
1261
if (p->pos < p->indexPreSize)
1262
{
1263
(*srcLen)++;
1264
if (*src++ != p->buf[p->pos++])
1265
return SZ_ERROR_CRC;
1266
}
1267
else
1268
{
1269
if (p->indexPos < p->indexSize)
1270
{
1271
UInt64 cur = p->indexSize - p->indexPos;
1272
if (srcRem > cur)
1273
srcRem = (SizeT)cur;
1274
p->crc = CrcUpdate(p->crc, src, srcRem);
1275
Sha256_Update(&p->sha, src, srcRem);
1276
(*srcLen) += srcRem;
1277
src += srcRem;
1278
p->indexPos += srcRem;
1279
}
1280
else if ((p->indexPos & 3) != 0)
1281
{
1282
Byte b = *src++;
1283
p->crc = CRC_UPDATE_BYTE(p->crc, b);
1284
(*srcLen)++;
1285
p->indexPos++;
1286
p->indexSize++;
1287
if (b != 0)
1288
return SZ_ERROR_CRC;
1289
}
1290
else
1291
{
1292
Byte digest[SHA256_DIGEST_SIZE];
1293
p->state = XZ_STATE_STREAM_INDEX_CRC;
1294
p->indexSize += 4;
1295
p->pos = 0;
1296
Sha256_Final(&p->sha, digest);
1297
if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1298
return SZ_ERROR_CRC;
1299
}
1300
}
1301
break;
1302
}
1303
1304
case XZ_STATE_STREAM_INDEX_CRC:
1305
{
1306
if (p->pos < 4)
1307
{
1308
(*srcLen)++;
1309
p->buf[p->pos++] = *src++;
1310
}
1311
else
1312
{
1313
const Byte *ptr = p->buf;
1314
p->state = XZ_STATE_STREAM_FOOTER;
1315
p->pos = 0;
1316
if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr))
1317
return SZ_ERROR_CRC;
1318
}
1319
break;
1320
}
1321
1322
case XZ_STATE_STREAM_FOOTER:
1323
{
1324
unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1325
if (cur > srcRem)
1326
cur = (unsigned)srcRem;
1327
memcpy(p->buf + p->pos, src, cur);
1328
p->pos += cur;
1329
(*srcLen) += cur;
1330
src += cur;
1331
if (p->pos == XZ_STREAM_FOOTER_SIZE)
1332
{
1333
p->state = XZ_STATE_STREAM_PADDING;
1334
p->numFinishedStreams++;
1335
p->padSize = 0;
1336
if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1337
return SZ_ERROR_CRC;
1338
}
1339
break;
1340
}
1341
1342
case XZ_STATE_STREAM_PADDING:
1343
{
1344
if (*src != 0)
1345
{
1346
if (((UInt32)p->padSize & 3) != 0)
1347
return SZ_ERROR_NO_ARCHIVE;
1348
p->pos = 0;
1349
p->state = XZ_STATE_STREAM_HEADER;
1350
}
1351
else
1352
{
1353
(*srcLen)++;
1354
src++;
1355
p->padSize++;
1356
}
1357
break;
1358
}
1359
1360
case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1361
1362
default: return SZ_ERROR_FAIL;
1363
}
1364
}
1365
/*
1366
if (p->state == XZ_STATE_FINISHED)
1367
*status = CODER_STATUS_FINISHED_WITH_MARK;
1368
return SZ_OK;
1369
*/
1370
}
1371
1372
1373
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1374
const Byte *src, SizeT *srcLen,
1375
ECoderFinishMode finishMode, ECoderStatus *status)
1376
{
1377
XzUnpacker_Init(p);
1378
XzUnpacker_SetOutBuf(p, dest, *destLen);
1379
1380
return XzUnpacker_Code(p,
1381
NULL, destLen,
1382
src, srcLen, True,
1383
finishMode, status);
1384
}
1385
1386
1387
BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1388
{
1389
return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1390
}
1391
1392
BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1393
{
1394
return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1395
}
1396
1397
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1398
{
1399
UInt64 num = 0;
1400
if (p->state == XZ_STATE_STREAM_PADDING)
1401
num = p->padSize;
1402
else if (p->state == XZ_STATE_STREAM_HEADER)
1403
num = p->padSize + p->pos;
1404
return num;
1405
}
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
#ifndef Z7_ST
1428
#include "MtDec.h"
1429
#endif
1430
1431
1432
void XzDecMtProps_Init(CXzDecMtProps *p)
1433
{
1434
p->inBufSize_ST = 1 << 18;
1435
p->outStep_ST = 1 << 20;
1436
p->ignoreErrors = False;
1437
1438
#ifndef Z7_ST
1439
p->numThreads = 1;
1440
p->inBufSize_MT = 1 << 18;
1441
p->memUseMax = sizeof(size_t) << 28;
1442
#endif
1443
}
1444
1445
1446
1447
#ifndef Z7_ST
1448
1449
/* ---------- CXzDecMtThread ---------- */
1450
1451
typedef struct
1452
{
1453
Byte *outBuf;
1454
size_t outBufSize;
1455
size_t outPreSize;
1456
size_t inPreSize;
1457
size_t inPreHeaderSize;
1458
size_t blockPackSize_for_Index; // including block header and checksum.
1459
size_t blockPackTotal; // including stream header, block header and checksum.
1460
size_t inCodeSize;
1461
size_t outCodeSize;
1462
ECoderStatus status;
1463
SRes codeRes;
1464
BoolInt skipMode;
1465
// BoolInt finishedWithMark;
1466
EMtDecParseState parseState;
1467
BoolInt parsing_Truncated;
1468
BoolInt atBlockHeader;
1469
CXzStreamFlags streamFlags;
1470
// UInt64 numFinishedStreams
1471
UInt64 numStreams;
1472
UInt64 numTotalBlocks;
1473
UInt64 numBlocks;
1474
1475
BoolInt dec_created;
1476
CXzUnpacker dec;
1477
1478
Byte mtPad[1 << 7];
1479
} CXzDecMtThread;
1480
1481
#endif
1482
1483
1484
/* ---------- CXzDecMt ---------- */
1485
1486
struct CXzDecMt
1487
{
1488
CAlignOffsetAlloc alignOffsetAlloc;
1489
ISzAllocPtr allocMid;
1490
1491
CXzDecMtProps props;
1492
size_t unpackBlockMaxSize;
1493
1494
ISeqInStreamPtr inStream;
1495
ISeqOutStreamPtr outStream;
1496
ICompressProgressPtr progress;
1497
1498
BoolInt finishMode;
1499
BoolInt outSize_Defined;
1500
UInt64 outSize;
1501
1502
UInt64 outProcessed;
1503
UInt64 inProcessed;
1504
UInt64 readProcessed;
1505
BoolInt readWasFinished;
1506
SRes readRes;
1507
SRes writeRes;
1508
1509
Byte *outBuf;
1510
size_t outBufSize;
1511
Byte *inBuf;
1512
size_t inBufSize;
1513
1514
CXzUnpacker dec;
1515
1516
ECoderStatus status;
1517
SRes codeRes;
1518
1519
#ifndef Z7_ST
1520
BoolInt mainDecoderWasCalled;
1521
// int statErrorDefined;
1522
int finishedDecoderIndex;
1523
1524
// global values that are used in Parse stage
1525
CXzStreamFlags streamFlags;
1526
// UInt64 numFinishedStreams
1527
UInt64 numStreams;
1528
UInt64 numTotalBlocks;
1529
UInt64 numBlocks;
1530
1531
// UInt64 numBadBlocks;
1532
SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage
1533
// it can be = SZ_ERROR_INPUT_EOF
1534
// it can be = SZ_ERROR_DATA, in some another cases
1535
BoolInt isBlockHeaderState_Parse;
1536
BoolInt isBlockHeaderState_Write;
1537
UInt64 outProcessed_Parse;
1538
BoolInt parsing_Truncated;
1539
1540
BoolInt mtc_WasConstructed;
1541
CMtDec mtc;
1542
CXzDecMtThread coders[MTDEC_THREADS_MAX];
1543
#endif
1544
};
1545
1546
1547
1548
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1549
{
1550
CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1551
if (!p)
1552
return NULL;
1553
1554
AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1555
p->alignOffsetAlloc.baseAlloc = alloc;
1556
p->alignOffsetAlloc.numAlignBits = 7;
1557
p->alignOffsetAlloc.offset = 0;
1558
1559
p->allocMid = allocMid;
1560
1561
p->outBuf = NULL;
1562
p->outBufSize = 0;
1563
p->inBuf = NULL;
1564
p->inBufSize = 0;
1565
1566
XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1567
1568
p->unpackBlockMaxSize = 0;
1569
1570
XzDecMtProps_Init(&p->props);
1571
1572
#ifndef Z7_ST
1573
p->mtc_WasConstructed = False;
1574
{
1575
unsigned i;
1576
for (i = 0; i < MTDEC_THREADS_MAX; i++)
1577
{
1578
CXzDecMtThread *coder = &p->coders[i];
1579
coder->dec_created = False;
1580
coder->outBuf = NULL;
1581
coder->outBufSize = 0;
1582
}
1583
}
1584
#endif
1585
1586
return (CXzDecMtHandle)p;
1587
}
1588
1589
1590
#ifndef Z7_ST
1591
1592
static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1593
{
1594
unsigned i;
1595
for (i = 0; i < MTDEC_THREADS_MAX; i++)
1596
{
1597
CXzDecMtThread *coder = &p->coders[i];
1598
if (coder->outBuf)
1599
{
1600
ISzAlloc_Free(p->allocMid, coder->outBuf);
1601
coder->outBuf = NULL;
1602
coder->outBufSize = 0;
1603
}
1604
}
1605
p->unpackBlockMaxSize = 0;
1606
}
1607
1608
#endif
1609
1610
1611
1612
static void XzDecMt_FreeSt(CXzDecMt *p)
1613
{
1614
XzUnpacker_Free(&p->dec);
1615
1616
if (p->outBuf)
1617
{
1618
ISzAlloc_Free(p->allocMid, p->outBuf);
1619
p->outBuf = NULL;
1620
}
1621
p->outBufSize = 0;
1622
1623
if (p->inBuf)
1624
{
1625
ISzAlloc_Free(p->allocMid, p->inBuf);
1626
p->inBuf = NULL;
1627
}
1628
p->inBufSize = 0;
1629
}
1630
1631
1632
// #define GET_CXzDecMt_p CXzDecMt *p = pp;
1633
1634
void XzDecMt_Destroy(CXzDecMtHandle p)
1635
{
1636
// GET_CXzDecMt_p
1637
1638
XzDecMt_FreeSt(p);
1639
1640
#ifndef Z7_ST
1641
1642
if (p->mtc_WasConstructed)
1643
{
1644
MtDec_Destruct(&p->mtc);
1645
p->mtc_WasConstructed = False;
1646
}
1647
{
1648
unsigned i;
1649
for (i = 0; i < MTDEC_THREADS_MAX; i++)
1650
{
1651
CXzDecMtThread *t = &p->coders[i];
1652
if (t->dec_created)
1653
{
1654
// we don't need to free dict here
1655
XzUnpacker_Free(&t->dec);
1656
t->dec_created = False;
1657
}
1658
}
1659
}
1660
XzDecMt_FreeOutBufs(p);
1661
1662
#endif
1663
1664
ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p);
1665
}
1666
1667
1668
1669
#ifndef Z7_ST
1670
1671
static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1672
{
1673
CXzDecMt *me = (CXzDecMt *)obj;
1674
CXzDecMtThread *coder = &me->coders[coderIndex];
1675
size_t srcSize = cc->srcSize;
1676
1677
cc->srcSize = 0;
1678
cc->outPos = 0;
1679
cc->state = MTDEC_PARSE_CONTINUE;
1680
1681
cc->canCreateNewThread = True;
1682
1683
if (cc->startCall)
1684
{
1685
coder->outPreSize = 0;
1686
coder->inPreSize = 0;
1687
coder->inPreHeaderSize = 0;
1688
coder->parseState = MTDEC_PARSE_CONTINUE;
1689
coder->parsing_Truncated = False;
1690
coder->skipMode = False;
1691
coder->codeRes = SZ_OK;
1692
coder->status = CODER_STATUS_NOT_SPECIFIED;
1693
coder->inCodeSize = 0;
1694
coder->outCodeSize = 0;
1695
1696
coder->numStreams = me->numStreams;
1697
coder->numTotalBlocks = me->numTotalBlocks;
1698
coder->numBlocks = me->numBlocks;
1699
1700
if (!coder->dec_created)
1701
{
1702
XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1703
coder->dec_created = True;
1704
}
1705
1706
XzUnpacker_Init(&coder->dec);
1707
1708
if (me->isBlockHeaderState_Parse)
1709
{
1710
coder->dec.streamFlags = me->streamFlags;
1711
coder->atBlockHeader = True;
1712
XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1713
}
1714
else
1715
{
1716
coder->atBlockHeader = False;
1717
me->isBlockHeaderState_Parse = True;
1718
}
1719
1720
coder->dec.numStartedStreams = me->numStreams;
1721
coder->dec.numTotalBlocks = me->numTotalBlocks;
1722
coder->dec.numBlocks = me->numBlocks;
1723
}
1724
1725
while (!coder->skipMode)
1726
{
1727
ECoderStatus status;
1728
SRes res;
1729
size_t srcSize2 = srcSize;
1730
size_t destSize = (size_t)0 - 1;
1731
1732
coder->dec.parseMode = True;
1733
coder->dec.headerParsedOk = False;
1734
1735
PRF_STR_INT("Parse", srcSize2)
1736
1737
res = XzUnpacker_Code(&coder->dec,
1738
NULL, &destSize,
1739
cc->src, &srcSize2, cc->srcFinished,
1740
CODER_FINISH_END, &status);
1741
1742
// PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1743
1744
coder->codeRes = res;
1745
coder->status = status;
1746
cc->srcSize += srcSize2;
1747
srcSize -= srcSize2;
1748
coder->inPreHeaderSize += srcSize2;
1749
coder->inPreSize = coder->inPreHeaderSize;
1750
1751
if (res != SZ_OK)
1752
{
1753
cc->state =
1754
coder->parseState = MTDEC_PARSE_END;
1755
/*
1756
if (res == SZ_ERROR_MEM)
1757
return res;
1758
return SZ_OK;
1759
*/
1760
return; // res;
1761
}
1762
1763
if (coder->dec.headerParsedOk)
1764
{
1765
const CXzBlock *block = &coder->dec.block;
1766
if (XzBlock_HasUnpackSize(block)
1767
// && block->unpackSize <= me->props.outBlockMax
1768
&& XzBlock_HasPackSize(block))
1769
{
1770
{
1771
if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1772
{
1773
cc->state = MTDEC_PARSE_OVERFLOW;
1774
return; // SZ_OK;
1775
}
1776
}
1777
{
1778
const UInt64 packSize = block->packSize;
1779
const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1780
const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1781
const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1782
// if (blockPackSum <= me->props.inBlockMax)
1783
// unpackBlockMaxSize
1784
{
1785
coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1786
coder->blockPackTotal = (size_t)blockPackSum;
1787
coder->outPreSize = (size_t)block->unpackSize;
1788
coder->streamFlags = coder->dec.streamFlags;
1789
me->streamFlags = coder->dec.streamFlags;
1790
coder->skipMode = True;
1791
break;
1792
}
1793
}
1794
}
1795
}
1796
else
1797
// if (coder->inPreSize <= me->props.inBlockMax)
1798
{
1799
if (!cc->srcFinished)
1800
return; // SZ_OK;
1801
cc->state =
1802
coder->parseState = MTDEC_PARSE_END;
1803
return; // SZ_OK;
1804
}
1805
cc->state = MTDEC_PARSE_OVERFLOW;
1806
return; // SZ_OK;
1807
}
1808
1809
// ---------- skipMode ----------
1810
{
1811
UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1812
size_t cur = srcSize;
1813
if (cur > rem)
1814
cur = (size_t)rem;
1815
cc->srcSize += cur;
1816
coder->inPreSize += cur;
1817
srcSize -= cur;
1818
1819
if (coder->inPreSize == coder->blockPackTotal)
1820
{
1821
if (srcSize == 0)
1822
{
1823
if (!cc->srcFinished)
1824
return; // SZ_OK;
1825
cc->state = MTDEC_PARSE_END;
1826
}
1827
else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1828
cc->state = MTDEC_PARSE_END;
1829
else
1830
{
1831
cc->state = MTDEC_PARSE_NEW;
1832
1833
{
1834
size_t blockMax = me->unpackBlockMaxSize;
1835
if (blockMax < coder->outPreSize)
1836
blockMax = coder->outPreSize;
1837
{
1838
UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1839
if (me->props.memUseMax < required)
1840
cc->canCreateNewThread = False;
1841
}
1842
}
1843
1844
if (me->outSize_Defined)
1845
{
1846
// next block can be zero size
1847
const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1848
if (rem2 < coder->outPreSize)
1849
{
1850
coder->parsing_Truncated = True;
1851
cc->state = MTDEC_PARSE_END;
1852
}
1853
me->outProcessed_Parse += coder->outPreSize;
1854
}
1855
}
1856
}
1857
else if (cc->srcFinished)
1858
cc->state = MTDEC_PARSE_END;
1859
else
1860
return; // SZ_OK;
1861
1862
coder->parseState = cc->state;
1863
cc->outPos = coder->outPreSize;
1864
1865
me->numStreams = coder->dec.numStartedStreams;
1866
me->numTotalBlocks = coder->dec.numTotalBlocks;
1867
me->numBlocks = coder->dec.numBlocks + 1;
1868
return; // SZ_OK;
1869
}
1870
}
1871
1872
1873
static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1874
{
1875
CXzDecMt *me = (CXzDecMt *)pp;
1876
CXzDecMtThread *coder = &me->coders[coderIndex];
1877
Byte *dest;
1878
1879
if (!coder->dec.headerParsedOk)
1880
return SZ_OK;
1881
1882
dest = coder->outBuf;
1883
1884
if (!dest || coder->outBufSize < coder->outPreSize)
1885
{
1886
if (dest)
1887
{
1888
ISzAlloc_Free(me->allocMid, dest);
1889
coder->outBuf = NULL;
1890
coder->outBufSize = 0;
1891
}
1892
{
1893
size_t outPreSize = coder->outPreSize;
1894
if (outPreSize == 0)
1895
outPreSize = 1;
1896
dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1897
}
1898
if (!dest)
1899
return SZ_ERROR_MEM;
1900
coder->outBuf = dest;
1901
coder->outBufSize = coder->outPreSize;
1902
1903
if (coder->outBufSize > me->unpackBlockMaxSize)
1904
me->unpackBlockMaxSize = coder->outBufSize;
1905
}
1906
1907
// return SZ_ERROR_MEM;
1908
1909
XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1910
1911
{
1912
SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1913
// res = SZ_ERROR_UNSUPPORTED; // to test
1914
coder->codeRes = res;
1915
if (res != SZ_OK)
1916
{
1917
// if (res == SZ_ERROR_MEM) return res;
1918
if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1919
return SZ_OK;
1920
return res;
1921
}
1922
}
1923
1924
return SZ_OK;
1925
}
1926
1927
1928
static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1929
const Byte *src, size_t srcSize, int srcFinished,
1930
// int finished, int blockFinished,
1931
UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1932
{
1933
CXzDecMt *me = (CXzDecMt *)pp;
1934
CXzDecMtThread *coder = &me->coders[coderIndex];
1935
1936
*inCodePos = coder->inCodeSize;
1937
*outCodePos = coder->outCodeSize;
1938
*stop = True;
1939
1940
if (srcSize > coder->inPreSize - coder->inCodeSize)
1941
return SZ_ERROR_FAIL;
1942
1943
if (coder->inCodeSize < coder->inPreHeaderSize)
1944
{
1945
size_t step = coder->inPreHeaderSize - coder->inCodeSize;
1946
if (step > srcSize)
1947
step = srcSize;
1948
src += step;
1949
srcSize -= step;
1950
coder->inCodeSize += step;
1951
*inCodePos = coder->inCodeSize;
1952
if (coder->inCodeSize < coder->inPreHeaderSize)
1953
{
1954
*stop = False;
1955
return SZ_OK;
1956
}
1957
}
1958
1959
if (!coder->dec.headerParsedOk)
1960
return SZ_OK;
1961
if (!coder->outBuf)
1962
return SZ_OK;
1963
1964
if (coder->codeRes == SZ_OK)
1965
{
1966
ECoderStatus status;
1967
SRes res;
1968
size_t srcProcessed = srcSize;
1969
size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1970
1971
// PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1972
1973
res = XzUnpacker_Code(&coder->dec,
1974
NULL, &outSizeCur,
1975
src, &srcProcessed, srcFinished,
1976
// coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1977
CODER_FINISH_END,
1978
&status);
1979
1980
// PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1981
1982
coder->codeRes = res;
1983
coder->status = status;
1984
coder->inCodeSize += srcProcessed;
1985
coder->outCodeSize = coder->dec.outDataWritten;
1986
*inCodePos = coder->inCodeSize;
1987
*outCodePos = coder->outCodeSize;
1988
1989
if (res == SZ_OK)
1990
{
1991
if (srcProcessed == srcSize)
1992
*stop = False;
1993
return SZ_OK;
1994
}
1995
}
1996
1997
if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1998
{
1999
*inCodePos = coder->inPreSize;
2000
*outCodePos = coder->outPreSize;
2001
return SZ_OK;
2002
}
2003
return coder->codeRes;
2004
}
2005
2006
2007
#define XZDECMT_STREAM_WRITE_STEP (1 << 24)
2008
2009
static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
2010
BoolInt needWriteToStream,
2011
const Byte *src, size_t srcSize, BoolInt isCross,
2012
// int srcFinished,
2013
BoolInt *needContinue,
2014
BoolInt *canRecode)
2015
{
2016
CXzDecMt *me = (CXzDecMt *)pp;
2017
const CXzDecMtThread *coder = &me->coders[coderIndex];
2018
2019
// PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
2020
2021
*needContinue = False;
2022
*canRecode = True;
2023
2024
if (!needWriteToStream)
2025
return SZ_OK;
2026
2027
if (!coder->dec.headerParsedOk || !coder->outBuf)
2028
{
2029
if (me->finishedDecoderIndex < 0)
2030
me->finishedDecoderIndex = (int)coderIndex;
2031
return SZ_OK;
2032
}
2033
2034
if (me->finishedDecoderIndex >= 0)
2035
return SZ_OK;
2036
2037
me->mtc.inProcessed += coder->inCodeSize;
2038
2039
*canRecode = False;
2040
2041
{
2042
SRes res;
2043
size_t size = coder->outCodeSize;
2044
Byte *data = coder->outBuf;
2045
2046
// we use in me->dec: sha, numBlocks, indexSize
2047
2048
if (!me->isBlockHeaderState_Write)
2049
{
2050
XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2051
me->dec.decodeOnlyOneBlock = False;
2052
me->dec.numStartedStreams = coder->dec.numStartedStreams;
2053
me->dec.streamFlags = coder->streamFlags;
2054
2055
me->isBlockHeaderState_Write = True;
2056
}
2057
2058
me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2059
XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2060
2061
if (coder->outPreSize != size)
2062
{
2063
if (me->props.ignoreErrors)
2064
{
2065
memset(data + size, 0, coder->outPreSize - size);
2066
size = coder->outPreSize;
2067
}
2068
// me->numBadBlocks++;
2069
if (me->mainErrorCode == SZ_OK)
2070
{
2071
if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2072
me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2073
else
2074
me->mainErrorCode = SZ_ERROR_DATA;
2075
}
2076
}
2077
2078
if (me->writeRes != SZ_OK)
2079
return me->writeRes;
2080
2081
res = SZ_OK;
2082
{
2083
if (me->outSize_Defined)
2084
{
2085
const UInt64 rem = me->outSize - me->outProcessed;
2086
if (size > rem)
2087
size = (SizeT)rem;
2088
}
2089
2090
for (;;)
2091
{
2092
size_t cur = size;
2093
size_t written;
2094
if (cur > XZDECMT_STREAM_WRITE_STEP)
2095
cur = XZDECMT_STREAM_WRITE_STEP;
2096
2097
written = ISeqOutStream_Write(me->outStream, data, cur);
2098
2099
// PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2100
2101
me->outProcessed += written;
2102
if (written != cur)
2103
{
2104
me->writeRes = SZ_ERROR_WRITE;
2105
res = me->writeRes;
2106
break;
2107
}
2108
data += cur;
2109
size -= cur;
2110
// PRF_STR_INT("Written size =", size)
2111
if (size == 0)
2112
break;
2113
res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2114
if (res != SZ_OK)
2115
break;
2116
}
2117
}
2118
2119
if (coder->codeRes != SZ_OK)
2120
if (!me->props.ignoreErrors)
2121
{
2122
me->finishedDecoderIndex = (int)coderIndex;
2123
return res;
2124
}
2125
2126
RINOK(res)
2127
2128
if (coder->inPreSize != coder->inCodeSize
2129
|| coder->blockPackTotal != coder->inCodeSize)
2130
{
2131
me->finishedDecoderIndex = (int)coderIndex;
2132
return SZ_OK;
2133
}
2134
2135
if (coder->parseState != MTDEC_PARSE_END)
2136
{
2137
*needContinue = True;
2138
return SZ_OK;
2139
}
2140
}
2141
2142
// (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2143
// so we can use mtc variables without lock
2144
2145
PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed)
2146
2147
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2148
{
2149
CXzUnpacker *dec = &me->dec;
2150
2151
PRF_STR_INT("PostSingle", srcSize)
2152
2153
{
2154
size_t srcProcessed = srcSize;
2155
ECoderStatus status;
2156
size_t outSizeCur = 0;
2157
SRes res;
2158
2159
// dec->decodeOnlyOneBlock = False;
2160
dec->decodeToStreamSignature = True;
2161
2162
me->mainDecoderWasCalled = True;
2163
2164
if (coder->parsing_Truncated)
2165
{
2166
me->parsing_Truncated = True;
2167
return SZ_OK;
2168
}
2169
2170
/*
2171
We have processed all xz-blocks of stream,
2172
And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where
2173
(src) is a pointer to xz-Index structure.
2174
We finish reading of current xz-Stream, including Zero padding after xz-Stream.
2175
We exit, if we reach extra byte (first byte of new-Stream or another data).
2176
But we don't update input stream pointer for that new extra byte.
2177
If extra byte is not correct first byte of xz-signature,
2178
we have SZ_ERROR_NO_ARCHIVE error here.
2179
*/
2180
2181
res = XzUnpacker_Code(dec,
2182
NULL, &outSizeCur,
2183
src, &srcProcessed,
2184
me->mtc.readWasFinished, // srcFinished
2185
CODER_FINISH_END, // CODER_FINISH_ANY,
2186
&status);
2187
2188
// res = SZ_ERROR_ARCHIVE; // for failure test
2189
2190
me->status = status;
2191
me->codeRes = res;
2192
2193
if (isCross)
2194
me->mtc.crossStart += srcProcessed;
2195
2196
me->mtc.inProcessed += srcProcessed;
2197
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2198
2199
srcSize -= srcProcessed;
2200
src += srcProcessed;
2201
2202
if (res != SZ_OK)
2203
{
2204
return SZ_OK;
2205
// return res;
2206
}
2207
2208
if (dec->state == XZ_STATE_STREAM_HEADER)
2209
{
2210
*needContinue = True;
2211
me->isBlockHeaderState_Parse = False;
2212
me->isBlockHeaderState_Write = False;
2213
2214
if (!isCross)
2215
{
2216
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2217
if (!crossBuf)
2218
return SZ_ERROR_MEM;
2219
if (srcSize != 0)
2220
memcpy(crossBuf, src, srcSize);
2221
me->mtc.crossStart = 0;
2222
me->mtc.crossEnd = srcSize;
2223
}
2224
2225
PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd)
2226
2227
return SZ_OK;
2228
}
2229
2230
if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0)
2231
{
2232
return SZ_ERROR_FAIL;
2233
}
2234
2235
if (me->mtc.readWasFinished)
2236
{
2237
return SZ_OK;
2238
}
2239
}
2240
2241
{
2242
size_t inPos;
2243
size_t inLim;
2244
// const Byte *inData;
2245
UInt64 inProgressPrev = me->mtc.inProcessed;
2246
2247
// XzDecMt_Prepare_InBuf_ST(p);
2248
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2249
if (!crossBuf)
2250
return SZ_ERROR_MEM;
2251
2252
inPos = 0;
2253
inLim = 0;
2254
2255
// inData = crossBuf;
2256
2257
for (;;)
2258
{
2259
SizeT inProcessed;
2260
SizeT outProcessed;
2261
ECoderStatus status;
2262
SRes res;
2263
2264
if (inPos == inLim)
2265
{
2266
if (!me->mtc.readWasFinished)
2267
{
2268
inPos = 0;
2269
inLim = me->mtc.inBufSize;
2270
me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim);
2271
me->mtc.readProcessed += inLim;
2272
if (inLim == 0 || me->mtc.readRes != SZ_OK)
2273
me->mtc.readWasFinished = True;
2274
}
2275
}
2276
2277
inProcessed = inLim - inPos;
2278
outProcessed = 0;
2279
2280
res = XzUnpacker_Code(dec,
2281
NULL, &outProcessed,
2282
crossBuf + inPos, &inProcessed,
2283
(inProcessed == 0), // srcFinished
2284
CODER_FINISH_END, &status);
2285
2286
me->codeRes = res;
2287
me->status = status;
2288
inPos += inProcessed;
2289
me->mtc.inProcessed += inProcessed;
2290
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2291
2292
if (res != SZ_OK)
2293
{
2294
return SZ_OK;
2295
// return res;
2296
}
2297
2298
if (dec->state == XZ_STATE_STREAM_HEADER)
2299
{
2300
*needContinue = True;
2301
me->mtc.crossStart = inPos;
2302
me->mtc.crossEnd = inLim;
2303
me->isBlockHeaderState_Parse = False;
2304
me->isBlockHeaderState_Write = False;
2305
return SZ_OK;
2306
}
2307
2308
if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2309
return SZ_ERROR_FAIL;
2310
2311
if (me->mtc.progress)
2312
{
2313
UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2314
if (inDelta >= (1 << 22))
2315
{
2316
RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress))
2317
inProgressPrev = me->mtc.inProcessed;
2318
}
2319
}
2320
if (me->mtc.readWasFinished)
2321
return SZ_OK;
2322
}
2323
}
2324
}
2325
}
2326
2327
2328
#endif
2329
2330
2331
2332
void XzStatInfo_Clear(CXzStatInfo *p)
2333
{
2334
p->InSize = 0;
2335
p->OutSize = 0;
2336
2337
p->NumStreams = 0;
2338
p->NumBlocks = 0;
2339
2340
p->UnpackSize_Defined = False;
2341
2342
p->NumStreams_Defined = False;
2343
p->NumBlocks_Defined = False;
2344
2345
p->DataAfterEnd = False;
2346
p->DecodingTruncated = False;
2347
2348
p->DecodeRes = SZ_OK;
2349
p->ReadRes = SZ_OK;
2350
p->ProgressRes = SZ_OK;
2351
2352
p->CombinedRes = SZ_OK;
2353
p->CombinedRes_Type = SZ_OK;
2354
}
2355
2356
2357
2358
/*
2359
XzDecMt_Decode_ST() can return SZ_OK or the following errors
2360
- SZ_ERROR_MEM for memory allocation error
2361
- error from XzUnpacker_Code() function
2362
- SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case
2363
- ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS.
2364
But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors.
2365
ISeqInStream::Read() result is set to p->readRes.
2366
also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
2367
*/
2368
2369
static SRes XzDecMt_Decode_ST(CXzDecMt *p
2370
#ifndef Z7_ST
2371
, BoolInt tMode
2372
#endif
2373
, CXzStatInfo *stat)
2374
{
2375
size_t outPos;
2376
size_t inPos, inLim;
2377
const Byte *inData;
2378
UInt64 inPrev, outPrev;
2379
2380
CXzUnpacker *dec;
2381
2382
#ifndef Z7_ST
2383
if (tMode)
2384
{
2385
XzDecMt_FreeOutBufs(p);
2386
tMode = (BoolInt)MtDec_PrepareRead(&p->mtc);
2387
}
2388
#endif
2389
2390
if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2391
{
2392
ISzAlloc_Free(p->allocMid, p->outBuf);
2393
p->outBufSize = 0;
2394
p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2395
if (!p->outBuf)
2396
return SZ_ERROR_MEM;
2397
p->outBufSize = p->props.outStep_ST;
2398
}
2399
2400
if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2401
{
2402
ISzAlloc_Free(p->allocMid, p->inBuf);
2403
p->inBufSize = 0;
2404
p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2405
if (!p->inBuf)
2406
return SZ_ERROR_MEM;
2407
p->inBufSize = p->props.inBufSize_ST;
2408
}
2409
2410
dec = &p->dec;
2411
dec->decodeToStreamSignature = False;
2412
// dec->decodeOnlyOneBlock = False;
2413
2414
XzUnpacker_SetOutBuf(dec, NULL, 0);
2415
2416
inPrev = p->inProcessed;
2417
outPrev = p->outProcessed;
2418
2419
inPos = 0;
2420
inLim = 0;
2421
inData = NULL;
2422
outPos = 0;
2423
2424
for (;;)
2425
{
2426
SizeT outSize;
2427
BoolInt finished;
2428
ECoderFinishMode finishMode;
2429
SizeT inProcessed;
2430
ECoderStatus status;
2431
SRes res;
2432
2433
SizeT outProcessed;
2434
2435
2436
2437
if (inPos == inLim)
2438
{
2439
#ifndef Z7_ST
2440
if (tMode)
2441
{
2442
inData = MtDec_Read(&p->mtc, &inLim);
2443
inPos = 0;
2444
if (inData)
2445
continue;
2446
tMode = False;
2447
inLim = 0;
2448
}
2449
#endif
2450
2451
if (!p->readWasFinished)
2452
{
2453
inPos = 0;
2454
inLim = p->inBufSize;
2455
inData = p->inBuf;
2456
p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim);
2457
p->readProcessed += inLim;
2458
if (inLim == 0 || p->readRes != SZ_OK)
2459
p->readWasFinished = True;
2460
}
2461
}
2462
2463
outSize = p->props.outStep_ST - outPos;
2464
2465
finishMode = CODER_FINISH_ANY;
2466
if (p->outSize_Defined)
2467
{
2468
const UInt64 rem = p->outSize - p->outProcessed;
2469
if (outSize >= rem)
2470
{
2471
outSize = (SizeT)rem;
2472
if (p->finishMode)
2473
finishMode = CODER_FINISH_END;
2474
}
2475
}
2476
2477
inProcessed = inLim - inPos;
2478
outProcessed = outSize;
2479
2480
res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2481
inData + inPos, &inProcessed,
2482
(inPos == inLim), // srcFinished
2483
finishMode, &status);
2484
2485
p->codeRes = res;
2486
p->status = status;
2487
2488
inPos += inProcessed;
2489
outPos += outProcessed;
2490
p->inProcessed += inProcessed;
2491
p->outProcessed += outProcessed;
2492
2493
finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2494
2495
if (finished || outProcessed >= outSize)
2496
if (outPos != 0)
2497
{
2498
const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2499
// p->outProcessed += written; // 21.01: BUG fixed
2500
if (written != outPos)
2501
{
2502
stat->CombinedRes_Type = SZ_ERROR_WRITE;
2503
return SZ_ERROR_WRITE;
2504
}
2505
outPos = 0;
2506
}
2507
2508
if (p->progress && res == SZ_OK)
2509
{
2510
if (p->inProcessed - inPrev >= (1 << 22) ||
2511
p->outProcessed - outPrev >= (1 << 22))
2512
{
2513
res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2514
if (res != SZ_OK)
2515
{
2516
stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2517
stat->ProgressRes = res;
2518
return res;
2519
}
2520
inPrev = p->inProcessed;
2521
outPrev = p->outProcessed;
2522
}
2523
}
2524
2525
if (finished)
2526
{
2527
// p->codeRes is preliminary error from XzUnpacker_Code.
2528
// and it can be corrected later as final result
2529
// so we return SZ_OK here instead of (res);
2530
return SZ_OK;
2531
// return res;
2532
}
2533
}
2534
}
2535
2536
2537
2538
/*
2539
XzStatInfo_SetStat() transforms
2540
CXzUnpacker return code and status to combined CXzStatInfo results.
2541
it can convert SZ_OK to SZ_ERROR_INPUT_EOF
2542
it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1)
2543
*/
2544
2545
static void XzStatInfo_SetStat(const CXzUnpacker *dec,
2546
int finishMode,
2547
// UInt64 readProcessed,
2548
UInt64 inProcessed,
2549
SRes res, // it's result from CXzUnpacker unpacker
2550
ECoderStatus status,
2551
BoolInt decodingTruncated,
2552
CXzStatInfo *stat)
2553
{
2554
UInt64 extraSize;
2555
2556
stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2557
stat->InSize = inProcessed;
2558
stat->NumStreams = dec->numStartedStreams;
2559
stat->NumBlocks = dec->numTotalBlocks;
2560
2561
stat->UnpackSize_Defined = True;
2562
stat->NumStreams_Defined = True;
2563
stat->NumBlocks_Defined = True;
2564
2565
extraSize = XzUnpacker_GetExtraSize(dec);
2566
2567
if (res == SZ_OK)
2568
{
2569
if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2570
{
2571
// CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2572
// any extra data is part of correct data
2573
extraSize = 0;
2574
// if xz stream was not finished, then we need more data
2575
if (!XzUnpacker_IsStreamWasFinished(dec))
2576
res = SZ_ERROR_INPUT_EOF;
2577
}
2578
else
2579
{
2580
// CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding
2581
// so he we have (status == CODER_STATUS_NOT_FINISHED)
2582
// if (status != CODER_STATUS_FINISHED_WITH_MARK)
2583
if (!decodingTruncated || finishMode)
2584
res = SZ_ERROR_DATA;
2585
}
2586
}
2587
else if (res == SZ_ERROR_NO_ARCHIVE)
2588
{
2589
/*
2590
SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2591
XZ_STATE_STREAM_HEADER - if bad signature or bad CRC
2592
XZ_STATE_STREAM_PADDING - if non-zero padding data
2593
extraSize and inProcessed don't include "bad" byte
2594
*/
2595
// if (inProcessed == extraSize), there was no any good xz stream header, and we keep error
2596
if (inProcessed != extraSize) // if there were good xz streams before error
2597
{
2598
// if (extraSize != 0 || readProcessed != inProcessed)
2599
{
2600
// he we suppose that all xz streams were finsihed OK, and we have
2601
// some extra data after all streams
2602
stat->DataAfterEnd = True;
2603
res = SZ_OK;
2604
}
2605
}
2606
}
2607
2608
if (stat->DecodeRes == SZ_OK)
2609
stat->DecodeRes = res;
2610
2611
stat->InSize -= extraSize;
2612
}
2613
2614
2615
2616
SRes XzDecMt_Decode(CXzDecMtHandle p,
2617
const CXzDecMtProps *props,
2618
const UInt64 *outDataSize, int finishMode,
2619
ISeqOutStreamPtr outStream,
2620
// Byte *outBuf, size_t *outBufSize,
2621
ISeqInStreamPtr inStream,
2622
// const Byte *inData, size_t inDataSize,
2623
CXzStatInfo *stat,
2624
int *isMT,
2625
ICompressProgressPtr progress)
2626
{
2627
// GET_CXzDecMt_p
2628
#ifndef Z7_ST
2629
BoolInt tMode;
2630
#endif
2631
2632
XzStatInfo_Clear(stat);
2633
2634
p->props = *props;
2635
2636
p->inStream = inStream;
2637
p->outStream = outStream;
2638
p->progress = progress;
2639
// p->stat = stat;
2640
2641
p->outSize = 0;
2642
p->outSize_Defined = False;
2643
if (outDataSize)
2644
{
2645
p->outSize_Defined = True;
2646
p->outSize = *outDataSize;
2647
}
2648
2649
p->finishMode = (BoolInt)finishMode;
2650
2651
// p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2652
2653
p->writeRes = SZ_OK;
2654
p->outProcessed = 0;
2655
p->inProcessed = 0;
2656
p->readProcessed = 0;
2657
p->readWasFinished = False;
2658
p->readRes = SZ_OK;
2659
2660
p->codeRes = SZ_OK;
2661
p->status = CODER_STATUS_NOT_SPECIFIED;
2662
2663
XzUnpacker_Init(&p->dec);
2664
2665
*isMT = False;
2666
2667
/*
2668
p->outBuf = NULL;
2669
p->outBufSize = 0;
2670
if (!outStream)
2671
{
2672
p->outBuf = outBuf;
2673
p->outBufSize = *outBufSize;
2674
*outBufSize = 0;
2675
}
2676
*/
2677
2678
2679
#ifndef Z7_ST
2680
2681
p->isBlockHeaderState_Parse = False;
2682
p->isBlockHeaderState_Write = False;
2683
// p->numBadBlocks = 0;
2684
p->mainErrorCode = SZ_OK;
2685
p->mainDecoderWasCalled = False;
2686
2687
tMode = False;
2688
2689
if (p->props.numThreads > 1)
2690
{
2691
IMtDecCallback2 vt;
2692
BoolInt needContinue;
2693
SRes res;
2694
// we just free ST buffers here
2695
// but we still keep state variables, that was set in XzUnpacker_Init()
2696
XzDecMt_FreeSt(p);
2697
2698
p->outProcessed_Parse = 0;
2699
p->parsing_Truncated = False;
2700
2701
p->numStreams = 0;
2702
p->numTotalBlocks = 0;
2703
p->numBlocks = 0;
2704
p->finishedDecoderIndex = -1;
2705
2706
if (!p->mtc_WasConstructed)
2707
{
2708
p->mtc_WasConstructed = True;
2709
MtDec_Construct(&p->mtc);
2710
}
2711
2712
p->mtc.mtCallback = &vt;
2713
p->mtc.mtCallbackObject = p;
2714
2715
p->mtc.progress = progress;
2716
p->mtc.inStream = inStream;
2717
p->mtc.alloc = &p->alignOffsetAlloc.vt;
2718
// p->mtc.inData = inData;
2719
// p->mtc.inDataSize = inDataSize;
2720
p->mtc.inBufSize = p->props.inBufSize_MT;
2721
// p->mtc.inBlockMax = p->props.inBlockMax;
2722
p->mtc.numThreadsMax = p->props.numThreads;
2723
2724
*isMT = True;
2725
2726
vt.Parse = XzDecMt_Callback_Parse;
2727
vt.PreCode = XzDecMt_Callback_PreCode;
2728
vt.Code = XzDecMt_Callback_Code;
2729
vt.Write = XzDecMt_Callback_Write;
2730
2731
2732
res = MtDec_Code(&p->mtc);
2733
2734
2735
stat->InSize = p->mtc.inProcessed;
2736
2737
p->inProcessed = p->mtc.inProcessed;
2738
p->readRes = p->mtc.readRes;
2739
p->readWasFinished = p->mtc.readWasFinished;
2740
p->readProcessed = p->mtc.readProcessed;
2741
2742
tMode = True;
2743
needContinue = False;
2744
2745
if (res == SZ_OK)
2746
{
2747
if (p->mtc.mtProgress.res != SZ_OK)
2748
{
2749
res = p->mtc.mtProgress.res;
2750
stat->ProgressRes = res;
2751
stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2752
}
2753
else
2754
needContinue = p->mtc.needContinue;
2755
}
2756
2757
if (!needContinue)
2758
{
2759
{
2760
SRes codeRes;
2761
BoolInt truncated = False;
2762
ECoderStatus status;
2763
const CXzUnpacker *dec;
2764
2765
stat->OutSize = p->outProcessed;
2766
2767
if (p->finishedDecoderIndex >= 0)
2768
{
2769
const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2770
codeRes = coder->codeRes;
2771
dec = &coder->dec;
2772
status = coder->status;
2773
}
2774
else if (p->mainDecoderWasCalled)
2775
{
2776
codeRes = p->codeRes;
2777
dec = &p->dec;
2778
status = p->status;
2779
truncated = p->parsing_Truncated;
2780
}
2781
else
2782
return SZ_ERROR_FAIL;
2783
2784
if (p->mainErrorCode != SZ_OK)
2785
stat->DecodeRes = p->mainErrorCode;
2786
2787
XzStatInfo_SetStat(dec, p->finishMode,
2788
// p->mtc.readProcessed,
2789
p->mtc.inProcessed,
2790
codeRes, status,
2791
truncated,
2792
stat);
2793
}
2794
2795
if (res == SZ_OK)
2796
{
2797
stat->ReadRes = p->mtc.readRes;
2798
2799
if (p->writeRes != SZ_OK)
2800
{
2801
res = p->writeRes;
2802
stat->CombinedRes_Type = SZ_ERROR_WRITE;
2803
}
2804
else if (p->mtc.readRes != SZ_OK
2805
// && p->mtc.inProcessed == p->mtc.readProcessed
2806
&& stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2807
{
2808
res = p->mtc.readRes;
2809
stat->CombinedRes_Type = SZ_ERROR_READ;
2810
}
2811
else if (stat->DecodeRes != SZ_OK)
2812
res = stat->DecodeRes;
2813
}
2814
2815
stat->CombinedRes = res;
2816
if (stat->CombinedRes_Type == SZ_OK)
2817
stat->CombinedRes_Type = res;
2818
return res;
2819
}
2820
2821
PRF_STR("----- decoding ST -----")
2822
}
2823
2824
#endif
2825
2826
2827
*isMT = False;
2828
2829
{
2830
SRes res = XzDecMt_Decode_ST(p
2831
#ifndef Z7_ST
2832
, tMode
2833
#endif
2834
, stat
2835
);
2836
2837
#ifndef Z7_ST
2838
// we must set error code from MT decoding at first
2839
if (p->mainErrorCode != SZ_OK)
2840
stat->DecodeRes = p->mainErrorCode;
2841
#endif
2842
2843
XzStatInfo_SetStat(&p->dec,
2844
p->finishMode,
2845
// p->readProcessed,
2846
p->inProcessed,
2847
p->codeRes, p->status,
2848
False, // truncated
2849
stat);
2850
2851
stat->ReadRes = p->readRes;
2852
2853
if (res == SZ_OK)
2854
{
2855
if (p->readRes != SZ_OK
2856
// && p->inProcessed == p->readProcessed
2857
&& stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2858
{
2859
// we set read error as combined error, only if that error was the reason
2860
// of decoding problem
2861
res = p->readRes;
2862
stat->CombinedRes_Type = SZ_ERROR_READ;
2863
}
2864
else if (stat->DecodeRes != SZ_OK)
2865
res = stat->DecodeRes;
2866
}
2867
2868
stat->CombinedRes = res;
2869
if (stat->CombinedRes_Type == SZ_OK)
2870
stat->CombinedRes_Type = res;
2871
return res;
2872
}
2873
}
2874
2875
#undef PRF
2876
#undef PRF_STR
2877
#undef PRF_STR_INT_2
2878
2879