Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/Lzma2Dec.c
4253 views
1
/* Lzma2Dec.c -- LZMA2 Decoder
2
2024-03-01 : Igor Pavlov : Public domain */
3
4
/* #define SHOW_DEBUG_INFO */
5
6
#include "Precomp.h"
7
8
#ifdef SHOW_DEBUG_INFO
9
#include <stdio.h>
10
#endif
11
12
#include <string.h>
13
14
#include "Lzma2Dec.h"
15
16
/*
17
00000000 - End of data
18
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
19
00000010 U U - Uncompressed, no reset
20
100uuuuu U U P P - LZMA, no reset
21
101uuuuu U U P P - LZMA, reset state
22
110uuuuu U U P P S - LZMA, reset state + set new prop
23
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
24
25
u, U - Unpack Size
26
P - Pack Size
27
S - Props
28
*/
29
30
#define LZMA2_CONTROL_COPY_RESET_DIC 1
31
32
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
33
34
#define LZMA2_LCLP_MAX 4
35
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
36
37
#ifdef SHOW_DEBUG_INFO
38
#define PRF(x) x
39
#else
40
#define PRF(x)
41
#endif
42
43
typedef enum
44
{
45
LZMA2_STATE_CONTROL,
46
LZMA2_STATE_UNPACK0,
47
LZMA2_STATE_UNPACK1,
48
LZMA2_STATE_PACK0,
49
LZMA2_STATE_PACK1,
50
LZMA2_STATE_PROP,
51
LZMA2_STATE_DATA,
52
LZMA2_STATE_DATA_CONT,
53
LZMA2_STATE_FINISHED,
54
LZMA2_STATE_ERROR
55
} ELzma2State;
56
57
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
58
{
59
UInt32 dicSize;
60
if (prop > 40)
61
return SZ_ERROR_UNSUPPORTED;
62
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
63
props[0] = (Byte)LZMA2_LCLP_MAX;
64
props[1] = (Byte)(dicSize);
65
props[2] = (Byte)(dicSize >> 8);
66
props[3] = (Byte)(dicSize >> 16);
67
props[4] = (Byte)(dicSize >> 24);
68
return SZ_OK;
69
}
70
71
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
72
{
73
Byte props[LZMA_PROPS_SIZE];
74
RINOK(Lzma2Dec_GetOldProps(prop, props))
75
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
76
}
77
78
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
79
{
80
Byte props[LZMA_PROPS_SIZE];
81
RINOK(Lzma2Dec_GetOldProps(prop, props))
82
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
83
}
84
85
void Lzma2Dec_Init(CLzma2Dec *p)
86
{
87
p->state = LZMA2_STATE_CONTROL;
88
p->needInitLevel = 0xE0;
89
p->isExtraMode = False;
90
p->unpackSize = 0;
91
92
// p->decoder.dicPos = 0; // we can use it instead of full init
93
LzmaDec_Init(&p->decoder);
94
}
95
96
// ELzma2State
97
static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
98
{
99
switch (p->state)
100
{
101
case LZMA2_STATE_CONTROL:
102
p->isExtraMode = False;
103
p->control = b;
104
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
105
PRF(printf(" %02X", (unsigned)b));
106
if (b == 0)
107
return LZMA2_STATE_FINISHED;
108
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109
{
110
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
111
p->needInitLevel = 0xC0;
112
else if (b > 2 || p->needInitLevel == 0xE0)
113
return LZMA2_STATE_ERROR;
114
}
115
else
116
{
117
if (b < p->needInitLevel)
118
return LZMA2_STATE_ERROR;
119
p->needInitLevel = 0;
120
p->unpackSize = (UInt32)(b & 0x1F) << 16;
121
}
122
return LZMA2_STATE_UNPACK0;
123
124
case LZMA2_STATE_UNPACK0:
125
p->unpackSize |= (UInt32)b << 8;
126
return LZMA2_STATE_UNPACK1;
127
128
case LZMA2_STATE_UNPACK1:
129
p->unpackSize |= (UInt32)b;
130
p->unpackSize++;
131
PRF(printf(" %7u", (unsigned)p->unpackSize));
132
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
133
134
case LZMA2_STATE_PACK0:
135
p->packSize = (UInt32)b << 8;
136
return LZMA2_STATE_PACK1;
137
138
case LZMA2_STATE_PACK1:
139
p->packSize |= (UInt32)b;
140
p->packSize++;
141
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
142
PRF(printf(" %5u", (unsigned)p->packSize));
143
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
144
145
case LZMA2_STATE_PROP:
146
{
147
unsigned lc, lp;
148
if (b >= (9 * 5 * 5))
149
return LZMA2_STATE_ERROR;
150
lc = b % 9;
151
b /= 9;
152
p->decoder.prop.pb = (Byte)(b / 5);
153
lp = b % 5;
154
if (lc + lp > LZMA2_LCLP_MAX)
155
return LZMA2_STATE_ERROR;
156
p->decoder.prop.lc = (Byte)lc;
157
p->decoder.prop.lp = (Byte)lp;
158
return LZMA2_STATE_DATA;
159
}
160
161
default:
162
return LZMA2_STATE_ERROR;
163
}
164
}
165
166
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
167
{
168
memcpy(p->dic + p->dicPos, src, size);
169
p->dicPos += size;
170
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
171
p->checkDicSize = p->prop.dicSize;
172
p->processedPos += (UInt32)size;
173
}
174
175
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
176
177
178
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
179
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
180
{
181
SizeT inSize = *srcLen;
182
*srcLen = 0;
183
*status = LZMA_STATUS_NOT_SPECIFIED;
184
185
while (p->state != LZMA2_STATE_ERROR)
186
{
187
SizeT dicPos;
188
189
if (p->state == LZMA2_STATE_FINISHED)
190
{
191
*status = LZMA_STATUS_FINISHED_WITH_MARK;
192
return SZ_OK;
193
}
194
195
dicPos = p->decoder.dicPos;
196
197
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
198
{
199
*status = LZMA_STATUS_NOT_FINISHED;
200
return SZ_OK;
201
}
202
203
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
204
{
205
if (*srcLen == inSize)
206
{
207
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
208
return SZ_OK;
209
}
210
(*srcLen)++;
211
p->state = Lzma2Dec_UpdateState(p, *src++);
212
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
213
break;
214
continue;
215
}
216
217
{
218
SizeT inCur = inSize - *srcLen;
219
SizeT outCur = dicLimit - dicPos;
220
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
221
222
if (outCur >= p->unpackSize)
223
{
224
outCur = (SizeT)p->unpackSize;
225
curFinishMode = LZMA_FINISH_END;
226
}
227
228
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
229
{
230
if (inCur == 0)
231
{
232
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
233
return SZ_OK;
234
}
235
236
if (p->state == LZMA2_STATE_DATA)
237
{
238
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
239
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
240
}
241
242
if (inCur > outCur)
243
inCur = outCur;
244
if (inCur == 0)
245
break;
246
247
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
248
249
src += inCur;
250
*srcLen += inCur;
251
p->unpackSize -= (UInt32)inCur;
252
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
253
}
254
else
255
{
256
SRes res;
257
258
if (p->state == LZMA2_STATE_DATA)
259
{
260
BoolInt initDic = (p->control >= 0xE0);
261
BoolInt initState = (p->control >= 0xA0);
262
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
263
p->state = LZMA2_STATE_DATA_CONT;
264
}
265
266
if (inCur > p->packSize)
267
inCur = (SizeT)p->packSize;
268
269
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
270
271
src += inCur;
272
*srcLen += inCur;
273
p->packSize -= (UInt32)inCur;
274
outCur = p->decoder.dicPos - dicPos;
275
p->unpackSize -= (UInt32)outCur;
276
277
if (res != 0)
278
break;
279
280
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
281
{
282
if (p->packSize == 0)
283
break;
284
return SZ_OK;
285
}
286
287
if (inCur == 0 && outCur == 0)
288
{
289
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
290
|| p->unpackSize != 0
291
|| p->packSize != 0)
292
break;
293
p->state = LZMA2_STATE_CONTROL;
294
}
295
296
*status = LZMA_STATUS_NOT_SPECIFIED;
297
}
298
}
299
}
300
301
*status = LZMA_STATUS_NOT_SPECIFIED;
302
p->state = LZMA2_STATE_ERROR;
303
return SZ_ERROR_DATA;
304
}
305
306
307
308
309
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
310
SizeT outSize,
311
const Byte *src, SizeT *srcLen,
312
int checkFinishBlock)
313
{
314
SizeT inSize = *srcLen;
315
*srcLen = 0;
316
317
while (p->state != LZMA2_STATE_ERROR)
318
{
319
if (p->state == LZMA2_STATE_FINISHED)
320
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
321
322
if (outSize == 0 && !checkFinishBlock)
323
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
324
325
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
326
{
327
if (*srcLen == inSize)
328
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
329
(*srcLen)++;
330
331
p->state = Lzma2Dec_UpdateState(p, *src++);
332
333
if (p->state == LZMA2_STATE_UNPACK0)
334
{
335
// if (p->decoder.dicPos != 0)
336
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
337
return LZMA2_PARSE_STATUS_NEW_BLOCK;
338
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
339
}
340
341
// The following code can be commented.
342
// It's not big problem, if we read additional input bytes.
343
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
344
345
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
346
{
347
// checkFinishBlock is true. So we expect that block must be finished,
348
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
349
// break;
350
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
351
}
352
353
if (p->state == LZMA2_STATE_DATA)
354
return LZMA2_PARSE_STATUS_NEW_CHUNK;
355
356
continue;
357
}
358
359
if (outSize == 0)
360
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
361
362
{
363
SizeT inCur = inSize - *srcLen;
364
365
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
366
{
367
if (inCur == 0)
368
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
369
if (inCur > p->unpackSize)
370
inCur = p->unpackSize;
371
if (inCur > outSize)
372
inCur = outSize;
373
p->decoder.dicPos += inCur;
374
src += inCur;
375
*srcLen += inCur;
376
outSize -= inCur;
377
p->unpackSize -= (UInt32)inCur;
378
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
379
}
380
else
381
{
382
p->isExtraMode = True;
383
384
if (inCur == 0)
385
{
386
if (p->packSize != 0)
387
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
388
}
389
else if (p->state == LZMA2_STATE_DATA)
390
{
391
p->state = LZMA2_STATE_DATA_CONT;
392
if (*src != 0)
393
{
394
// first byte of lzma chunk must be Zero
395
*srcLen += 1;
396
p->packSize--;
397
break;
398
}
399
}
400
401
if (inCur > p->packSize)
402
inCur = (SizeT)p->packSize;
403
404
src += inCur;
405
*srcLen += inCur;
406
p->packSize -= (UInt32)inCur;
407
408
if (p->packSize == 0)
409
{
410
SizeT rem = outSize;
411
if (rem > p->unpackSize)
412
rem = p->unpackSize;
413
p->decoder.dicPos += rem;
414
p->unpackSize -= (UInt32)rem;
415
outSize -= rem;
416
if (p->unpackSize == 0)
417
p->state = LZMA2_STATE_CONTROL;
418
}
419
}
420
}
421
}
422
423
p->state = LZMA2_STATE_ERROR;
424
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
425
}
426
427
428
429
430
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
431
{
432
SizeT outSize = *destLen, inSize = *srcLen;
433
*srcLen = *destLen = 0;
434
435
for (;;)
436
{
437
SizeT inCur = inSize, outCur, dicPos;
438
ELzmaFinishMode curFinishMode;
439
SRes res;
440
441
if (p->decoder.dicPos == p->decoder.dicBufSize)
442
p->decoder.dicPos = 0;
443
dicPos = p->decoder.dicPos;
444
curFinishMode = LZMA_FINISH_ANY;
445
outCur = p->decoder.dicBufSize - dicPos;
446
447
if (outCur >= outSize)
448
{
449
outCur = outSize;
450
curFinishMode = finishMode;
451
}
452
453
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
454
455
src += inCur;
456
inSize -= inCur;
457
*srcLen += inCur;
458
outCur = p->decoder.dicPos - dicPos;
459
memcpy(dest, p->decoder.dic + dicPos, outCur);
460
dest += outCur;
461
outSize -= outCur;
462
*destLen += outCur;
463
if (res != 0)
464
return res;
465
if (outCur == 0 || outSize == 0)
466
return SZ_OK;
467
}
468
}
469
470
471
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
472
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
473
{
474
CLzma2Dec p;
475
SRes res;
476
SizeT outSize = *destLen, inSize = *srcLen;
477
*destLen = *srcLen = 0;
478
*status = LZMA_STATUS_NOT_SPECIFIED;
479
Lzma2Dec_CONSTRUCT(&p)
480
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
481
p.decoder.dic = dest;
482
p.decoder.dicBufSize = outSize;
483
Lzma2Dec_Init(&p);
484
*srcLen = inSize;
485
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
486
*destLen = p.decoder.dicPos;
487
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
488
res = SZ_ERROR_INPUT_EOF;
489
Lzma2Dec_FreeProbs(&p, alloc);
490
return res;
491
}
492
493
#undef PRF
494
495