1 // LzfseDecoder.cpp
2
3 /*
4 This code implements LZFSE data decompressing.
5 The code from "LZFSE compression library" was used.
6
7 2018 : Igor Pavlov : BSD 3-clause License : the code in this file
8 2015-2017 : Apple Inc : BSD 3-clause License : original "LZFSE compression library" code
9
10 The code in the "LZFSE compression library" is licensed under the "BSD 3-clause License":
11 ----
12 Copyright (c) 2015-2016, Apple Inc. All rights reserved.
13
14 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
15
16 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
17
18 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
19 in the documentation and/or other materials provided with the distribution.
20
21 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
22 from this software without specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ----
31 */
32
33 #include "StdAfx.h"
34
35 // #define SHOW_DEBUG_INFO
36
37 #ifdef SHOW_DEBUG_INFO
38 #include <stdio.h>
39 #endif
40
41 #ifdef SHOW_DEBUG_INFO
42 #define PRF(x) x
43 #else
44 #define PRF(x)
45 #endif
46
47 #include "../../../C/CpuArch.h"
48
49 #include "LzfseDecoder.h"
50
51 namespace NCompress {
52 namespace NLzfse {
53
54 static const Byte kSignature_LZFSE_V1 = 0x31; // '1'
55 static const Byte kSignature_LZFSE_V2 = 0x32; // '2'
56
57
GetUInt32(UInt32 & val)58 HRESULT CDecoder::GetUInt32(UInt32 &val)
59 {
60 Byte b[4];
61 for (unsigned i = 0; i < 4; i++)
62 if (!m_InStream.ReadByte(b[i]))
63 return S_FALSE;
64 val = GetUi32(b);
65 return S_OK;
66 }
67
68
69
DecodeUncompressed(UInt32 unpackSize)70 HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)
71 {
72 PRF(printf("\nUncompressed %7u\n", unpackSize));
73
74 const unsigned kBufSize = 1 << 8;
75 Byte buf[kBufSize];
76 for (;;)
77 {
78 if (unpackSize == 0)
79 return S_OK;
80 UInt32 cur = unpackSize;
81 if (cur > kBufSize)
82 cur = kBufSize;
83 UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur);
84 m_OutWindowStream.PutBytes(buf, cur2);
85 if (cur != cur2)
86 return S_FALSE;
87 }
88 }
89
90
91
DecodeLzvn(UInt32 unpackSize)92 HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize)
93 {
94 UInt32 packSize;
95 RINOK(GetUInt32(packSize));
96
97 PRF(printf("\nLZVN %7u %7u", unpackSize, packSize));
98
99 UInt32 D = 0;
100
101 for (;;)
102 {
103 if (packSize == 0)
104 return S_FALSE;
105 Byte b;
106 if (!m_InStream.ReadByte(b))
107 return S_FALSE;
108 packSize--;
109
110 UInt32 M;
111 UInt32 L;
112
113 if (b >= 0xE0)
114 {
115 /*
116 large L - 11100000 LLLLLLLL <LITERALS>
117 small L - 1110LLLL <LITERALS>
118
119 large Rep - 11110000 MMMMMMMM
120 small Rep - 1111MMMM
121 */
122
123 M = b & 0xF;
124 if (M == 0)
125 {
126 if (packSize == 0)
127 return S_FALSE;
128 Byte b1;
129 if (!m_InStream.ReadByte(b1))
130 return S_FALSE;
131 packSize--;
132 M = (UInt32)b1 + 16;
133 }
134 L = 0;
135 if ((b & 0x10) == 0)
136 {
137 // Literals only
138 L = M;
139 M = 0;
140 }
141 }
142
143 // ERROR codes
144 else if ((b & 0xF0) == 0x70) // 0111xxxx
145 return S_FALSE;
146 else if ((b & 0xF0) == 0xD0) // 1101xxxx
147 return S_FALSE;
148
149 else
150 {
151 if ((b & 0xE0) == 0xA0)
152 {
153 // medium - 101LLMMM DDDDDDMM DDDDDDDD <LITERALS>
154 if (packSize < 2)
155 return S_FALSE;
156 Byte b1;
157 if (!m_InStream.ReadByte(b1))
158 return S_FALSE;
159 packSize--;
160
161 Byte b2;
162 if (!m_InStream.ReadByte(b2))
163 return S_FALSE;
164 packSize--;
165 L = (((UInt32)b >> 3) & 3);
166 M = (((UInt32)b & 7) << 2) + (b1 & 3);
167 D = ((UInt32)b1 >> 2) + ((UInt32)b2 << 6);
168 }
169 else
170 {
171 L = (UInt32)b >> 6;
172 M = ((UInt32)b >> 3) & 7;
173 if ((b & 0x7) == 6)
174 {
175 // REP - LLMMM110 <LITERALS>
176 if (L == 0)
177 {
178 // spec
179 if (M == 0)
180 break; // EOS
181 if (M <= 2)
182 continue; // NOP
183 return S_FALSE; // UNDEFINED
184 }
185 }
186 else
187 {
188 if (packSize == 0)
189 return S_FALSE;
190 Byte b1;
191 if (!m_InStream.ReadByte(b1))
192 return S_FALSE;
193 packSize--;
194
195 // large - LLMMM111 DDDDDDDD DDDDDDDD <LITERALS>
196 // small - LLMMMDDD DDDDDDDD <LITERALS>
197 D = ((UInt32)b & 7);
198 if (D == 7)
199 {
200 if (packSize == 0)
201 return S_FALSE;
202 Byte b2;
203 if (!m_InStream.ReadByte(b2))
204 return S_FALSE;
205 packSize--;
206 D = b2;
207 }
208 D = (D << 8) + b1;
209 }
210 }
211
212 M += 3;
213 }
214 {
215 for (unsigned i = 0; i < L; i++)
216 {
217 if (packSize == 0 || unpackSize == 0)
218 return S_FALSE;
219 Byte b1;
220 if (!m_InStream.ReadByte(b1))
221 return S_FALSE;
222 packSize--;
223 m_OutWindowStream.PutByte(b1);
224 unpackSize--;
225 }
226 }
227
228 if (M != 0)
229 {
230 if (unpackSize == 0 || D == 0)
231 return S_FALSE;
232 unsigned cur = M;
233 if (cur > unpackSize)
234 cur = (unsigned)unpackSize;
235 if (!m_OutWindowStream.CopyBlock(D - 1, cur))
236 return S_FALSE;
237 unpackSize -= cur;
238 if (cur != M)
239 return S_FALSE;
240 }
241 }
242
243 if (unpackSize != 0)
244 return S_FALSE;
245
246 // LZVN encoder writes 7 additional zero bytes
247 if (packSize != 7)
248 return S_FALSE;
249 do
250 {
251 Byte b;
252 if (!m_InStream.ReadByte(b))
253 return S_FALSE;
254 packSize--;
255 if (b != 0)
256 return S_FALSE;
257 }
258 while (packSize != 0);
259
260 return S_OK;
261 }
262
263
264
265 // ---------- LZFSE ----------
266
267 #define MATCHES_PER_BLOCK 10000
268 #define LITERALS_PER_BLOCK (4 * MATCHES_PER_BLOCK)
269
270 #define NUM_L_SYMBOLS 20
271 #define NUM_M_SYMBOLS 20
272 #define NUM_D_SYMBOLS 64
273 #define NUM_LIT_SYMBOLS 256
274
275 #define NUM_SYMBOLS ( \
276 NUM_L_SYMBOLS + \
277 NUM_M_SYMBOLS + \
278 NUM_D_SYMBOLS + \
279 NUM_LIT_SYMBOLS)
280
281 #define NUM_L_STATES (1 << 6)
282 #define NUM_M_STATES (1 << 6)
283 #define NUM_D_STATES (1 << 8)
284 #define NUM_LIT_STATES (1 << 10)
285
286
287 typedef UInt32 CFseState;
288
289
SumFreqs(const UInt16 * freqs,unsigned num)290 static UInt32 SumFreqs(const UInt16 *freqs, unsigned num)
291 {
292 UInt32 sum = 0;
293 for (unsigned i = 0; i < num; i++)
294 sum += (UInt32)freqs[i];
295 return sum;
296 }
297
298
CountZeroBits(UInt32 val,UInt32 mask)299 static MY_FORCE_INLINE unsigned CountZeroBits(UInt32 val, UInt32 mask)
300 {
301 for (unsigned i = 0;;)
302 {
303 if (val & mask)
304 return i;
305 i++;
306 mask >>= 1;
307 }
308 }
309
310
InitLitTable(const UInt16 * freqs,UInt32 * table)311 static MY_FORCE_INLINE void InitLitTable(const UInt16 *freqs, UInt32 *table)
312 {
313 for (unsigned i = 0; i < NUM_LIT_SYMBOLS; i++)
314 {
315 unsigned f = freqs[i];
316 if (f == 0)
317 continue;
318
319 // 0 < f <= numStates
320 // 0 <= k <= numStatesLog
321 // numStates <= (f<<k) < numStates * 2
322 // 0 < j0 <= f
323 // (f + j0) = next_power_of_2 for f
324 unsigned k = CountZeroBits(f, NUM_LIT_STATES);
325 unsigned j0 = (((unsigned)NUM_LIT_STATES * 2) >> k) - f;
326
327 /*
328 CEntry
329 {
330 Byte k;
331 Byte symbol;
332 UInt16 delta;
333 };
334 */
335
336 UInt32 e = ((UInt32)i << 8) + k;
337 k += 16;
338 UInt32 d = e + ((UInt32)f << k) - ((UInt32)NUM_LIT_STATES << 16);
339 UInt32 step = (UInt32)1 << k;
340
341 unsigned j = 0;
342 do
343 {
344 *table++ = d;
345 d += step;
346 }
347 while (++j < j0);
348
349 e--;
350 step >>= 1;
351
352 for (j = j0; j < f; j++)
353 {
354 *table++ = e;
355 e += step;
356 }
357 }
358 }
359
360
361 typedef struct
362 {
363 Byte totalBits;
364 Byte extraBits;
365 UInt16 delta;
366 UInt32 vbase;
367 } CExtraEntry;
368
369
InitExtraDecoderTable(unsigned numStates,unsigned numSymbols,const UInt16 * freqs,const Byte * vbits,CExtraEntry * table)370 static void InitExtraDecoderTable(unsigned numStates,
371 unsigned numSymbols,
372 const UInt16 *freqs,
373 const Byte *vbits,
374 CExtraEntry *table)
375 {
376 UInt32 vbase = 0;
377
378 for (unsigned i = 0; i < numSymbols; i++)
379 {
380 unsigned f = freqs[i];
381 unsigned extraBits = vbits[i];
382
383 if (f != 0)
384 {
385 unsigned k = CountZeroBits(f, numStates);
386 unsigned j0 = ((2 * numStates) >> k) - f;
387
388 unsigned j = 0;
389 do
390 {
391 CExtraEntry *e = table++;
392 e->totalBits = (Byte)(k + extraBits);
393 e->extraBits = (Byte)extraBits;
394 e->delta = (UInt16)(((f + j) << k) - numStates);
395 e->vbase = vbase;
396 }
397 while (++j < j0);
398
399 f -= j0;
400 k--;
401
402 for (j = 0; j < f; j++)
403 {
404 CExtraEntry *e = table++;
405 e->totalBits = (Byte)(k + extraBits);
406 e->extraBits = (Byte)extraBits;
407 e->delta = (UInt16)(j << k);
408 e->vbase = vbase;
409 }
410 }
411
412 vbase += ((UInt32)1 << extraBits);
413 }
414 }
415
416
417 static const Byte k_L_extra[NUM_L_SYMBOLS] =
418 {
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8
420 };
421
422 static const Byte k_M_extra[NUM_M_SYMBOLS] =
423 {
424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11
425 };
426
427 static const Byte k_D_extra[NUM_D_SYMBOLS] =
428 {
429 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
430 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
431 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
432 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15
433 };
434
435
436
437 // ---------- CBitStream ----------
438
439 typedef struct
440 {
441 UInt32 accum;
442 unsigned numBits; // [0, 31] - Number of valid bits in (accum), other bits are 0
443 } CBitStream;
444
445
FseInStream_Init(CBitStream * s,int n,const Byte ** pbuf)446 static MY_FORCE_INLINE int FseInStream_Init(CBitStream *s,
447 int n, // [-7, 0], (-n == number_of_unused_bits) in last byte
448 const Byte **pbuf)
449 {
450 *pbuf -= 4;
451 s->accum = GetUi32(*pbuf);
452 if (n)
453 {
454 s->numBits = n + 32;
455 if ((s->accum >> s->numBits) != 0)
456 return -1; // ERROR, encoder should have zeroed the upper bits
457 }
458 else
459 {
460 *pbuf += 1;
461 s->accum >>= 8;
462 s->numBits = 24;
463 }
464 return 0; // OK
465 }
466
467
468 // 0 <= numBits < 32
469 #define mask31(x, numBits) ((x) & (((UInt32)1 << (numBits)) - 1))
470
471 #define FseInStream_FLUSH \
472 { unsigned nbits = (31 - in.numBits) & -8; \
473 if (nbits) { \
474 buf -= (nbits >> 3); \
475 if (buf < buf_check) return S_FALSE; \
476 UInt32 v = GetUi32(buf); \
477 in.accum = (in.accum << nbits) | mask31(v, nbits); \
478 in.numBits += nbits; }}
479
480
481
BitStream_Pull(CBitStream * s,unsigned numBits)482 static MY_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits)
483 {
484 s->numBits -= numBits;
485 UInt32 v = s->accum >> s->numBits;
486 s->accum = mask31(s->accum, s->numBits);
487 return v;
488 }
489
490
491 #define DECODE_LIT(dest, pstate) { \
492 UInt32 e = lit_decoder[pstate]; \
493 pstate = (CFseState)((e >> 16) + BitStream_Pull(&in, e & 0xff)); \
494 dest = (Byte)(e >> 8); }
495
496
FseDecodeExtra(CFseState * pstate,const CExtraEntry * table,CBitStream * s)497 static MY_FORCE_INLINE UInt32 FseDecodeExtra(CFseState *pstate,
498 const CExtraEntry *table,
499 CBitStream *s)
500 {
501 const CExtraEntry *e = &table[*pstate];
502 UInt32 v = BitStream_Pull(s, e->totalBits);
503 unsigned extraBits = e->extraBits;
504 *pstate = (CFseState)(e->delta + (v >> extraBits));
505 return e->vbase + mask31(v, extraBits);
506 }
507
508
509 #define freqs_L (freqs)
510 #define freqs_M (freqs_L + NUM_L_SYMBOLS)
511 #define freqs_D (freqs_M + NUM_M_SYMBOLS)
512 #define freqs_LIT (freqs_D + NUM_D_SYMBOLS)
513
514 #define GET_BITS_64(v, offset, num, dest) dest = (UInt32) ((v >> (offset)) & ((1 << (num)) - 1));
515 #define GET_BITS_32(v, offset, num, dest) dest = (CFseState)((v >> (offset)) & ((1 << (num)) - 1));
516
517
DecodeLzfse(UInt32 unpackSize,Byte version)518 HRESULT CDecoder::DecodeLzfse(UInt32 unpackSize, Byte version)
519 {
520 PRF(printf("\nLZFSE-%d %7u", version - '0', unpackSize));
521
522 UInt32 numLiterals;
523 UInt32 litPayloadSize;
524 Int32 literal_bits;
525
526 UInt32 lit_state_0;
527 UInt32 lit_state_1;
528 UInt32 lit_state_2;
529 UInt32 lit_state_3;
530
531 UInt32 numMatches;
532 UInt32 lmdPayloadSize;
533 Int32 lmd_bits;
534
535 CFseState l_state;
536 CFseState m_state;
537 CFseState d_state;
538
539 UInt16 freqs[NUM_SYMBOLS];
540
541 if (version == kSignature_LZFSE_V1)
542 {
543 return E_NOTIMPL;
544 // we need examples to test LZFSE-V1 code
545 /*
546 const unsigned k_v1_SubHeaderSize = 7 * 4 + 7 * 2;
547 const unsigned k_v1_HeaderSize = k_v1_SubHeaderSize + NUM_SYMBOLS * 2;
548 _buffer.AllocAtLeast(k_v1_HeaderSize);
549 if (m_InStream.ReadBytes(_buffer, k_v1_HeaderSize) != k_v1_HeaderSize)
550 return S_FALSE;
551
552 const Byte *buf = _buffer;
553 #define GET_32(offs, dest) dest = GetUi32(buf + offs)
554 #define GET_16(offs, dest) dest = GetUi16(buf + offs)
555
556 UInt32 payload_bytes;
557 GET_32(0, payload_bytes);
558 GET_32(4, numLiterals);
559 GET_32(8, numMatches);
560 GET_32(12, litPayloadSize);
561 GET_32(16, lmdPayloadSize);
562 if (litPayloadSize > (1 << 20) || lmdPayloadSize > (1 << 20))
563 return S_FALSE;
564 GET_32(20, literal_bits);
565 if (literal_bits < -7 || literal_bits > 0)
566 return S_FALSE;
567
568 GET_16(24, lit_state_0);
569 GET_16(26, lit_state_1);
570 GET_16(28, lit_state_2);
571 GET_16(30, lit_state_3);
572
573 GET_32(32, lmd_bits);
574 if (lmd_bits < -7 || lmd_bits > 0)
575 return S_FALSE;
576
577 GET_16(36, l_state);
578 GET_16(38, m_state);
579 GET_16(40, d_state);
580
581 for (unsigned i = 0; i < NUM_SYMBOLS; i++)
582 freqs[i] = GetUi16(buf + k_v1_SubHeaderSize + i * 2);
583 */
584 }
585 else
586 {
587 UInt32 headerSize;
588 {
589 const unsigned kPreHeaderSize = 4 * 2; // signature and upackSize
590 const unsigned kHeaderSize = 8 * 3;
591 Byte temp[kHeaderSize];
592 if (m_InStream.ReadBytes(temp, kHeaderSize) != kHeaderSize)
593 return S_FALSE;
594
595 UInt64 v;
596
597 v = GetUi64(temp);
598 GET_BITS_64(v, 0, 20, numLiterals);
599 GET_BITS_64(v, 20, 20, litPayloadSize);
600 GET_BITS_64(v, 40, 20, numMatches);
601 GET_BITS_64(v, 60, 3 + 1, literal_bits); // (NumberOfUsedBits - 1)
602 literal_bits -= 7; // (-NumberOfUnusedBits)
603 if (literal_bits > 0)
604 return S_FALSE;
605 // GET_BITS_64(v, 63, 1, unused);
606
607 v = GetUi64(temp + 8);
608 GET_BITS_64(v, 0, 10, lit_state_0);
609 GET_BITS_64(v, 10, 10, lit_state_1);
610 GET_BITS_64(v, 20, 10, lit_state_2);
611 GET_BITS_64(v, 30, 10, lit_state_3);
612 GET_BITS_64(v, 40, 20, lmdPayloadSize);
613 GET_BITS_64(v, 60, 3 + 1, lmd_bits);
614 lmd_bits -= 7;
615 if (lmd_bits > 0)
616 return S_FALSE;
617 // GET_BITS_64(v, 63, 1, unused)
618
619 UInt32 v32 = GetUi32(temp + 20);
620 // (total header size in bytes; this does not
621 // correspond to a field in the uncompressed header version,
622 // but is required; we wouldn't know the size of the
623 // compresssed header otherwise.
624 GET_BITS_32(v32, 0, 10, l_state);
625 GET_BITS_32(v32, 10, 10, m_state);
626 GET_BITS_32(v32, 20, 10 + 2, d_state);
627 // GET_BITS_64(v, 62, 2, unused);
628
629 headerSize = GetUi32(temp + 16);
630 if (headerSize <= kPreHeaderSize + kHeaderSize)
631 return S_FALSE;
632 headerSize -= kPreHeaderSize + kHeaderSize;
633 }
634
635 // no freqs case is not allowed ?
636 // memset(freqs, 0, sizeof(freqs));
637 // if (headerSize != 0)
638 {
639 static const Byte numBitsTable[32] =
640 {
641 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14,
642 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14
643 };
644
645 static const Byte valueTable[32] =
646 {
647 0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 24,
648 0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 24
649 };
650
651 UInt32 accum = 0;
652 unsigned numBits = 0;
653
654 for (unsigned i = 0; i < NUM_SYMBOLS; i++)
655 {
656 while (numBits <= 14 && headerSize != 0)
657 {
658 Byte b;
659 if (!m_InStream.ReadByte(b))
660 return S_FALSE;
661 accum |= (UInt32)b << numBits;
662 numBits += 8;
663 headerSize--;
664 }
665
666 unsigned b = (unsigned)accum & 31;
667 unsigned n = numBitsTable[b];
668 if (numBits < n)
669 return S_FALSE;
670 numBits -= n;
671 UInt32 f = valueTable[b];
672 if (n >= 8)
673 f += ((accum >> 4) & (0x3ff >> (14 - n)));
674 accum >>= n;
675 freqs[i] = (UInt16)f;
676 }
677
678 if (numBits >= 8 || headerSize != 0)
679 return S_FALSE;
680 }
681 }
682
683 PRF(printf(" Literals=%6u Matches=%6u", numLiterals, numMatches));
684
685 if (numLiterals > LITERALS_PER_BLOCK
686 || (numLiterals & 3) != 0
687 || numMatches > MATCHES_PER_BLOCK
688 || lit_state_0 >= NUM_LIT_STATES
689 || lit_state_1 >= NUM_LIT_STATES
690 || lit_state_2 >= NUM_LIT_STATES
691 || lit_state_3 >= NUM_LIT_STATES
692 || l_state >= NUM_L_STATES
693 || m_state >= NUM_M_STATES
694 || d_state >= NUM_D_STATES)
695 return S_FALSE;
696
697 // only full table is allowed ?
698 if ( SumFreqs(freqs_L, NUM_L_SYMBOLS) != NUM_L_STATES
699 || SumFreqs(freqs_M, NUM_M_SYMBOLS) != NUM_M_STATES
700 || SumFreqs(freqs_D, NUM_D_SYMBOLS) != NUM_D_STATES
701 || SumFreqs(freqs_LIT, NUM_LIT_SYMBOLS) != NUM_LIT_STATES)
702 return S_FALSE;
703
704
705 const unsigned kPad = 16;
706
707 // ---------- Decode literals ----------
708
709 {
710 _literals.AllocAtLeast(LITERALS_PER_BLOCK + 16);
711 _buffer.AllocAtLeast(kPad + litPayloadSize);
712 memset(_buffer, 0, kPad);
713
714 if (m_InStream.ReadBytes(_buffer + kPad, litPayloadSize) != litPayloadSize)
715 return S_FALSE;
716
717 UInt32 lit_decoder[NUM_LIT_STATES];
718 InitLitTable(freqs_LIT, lit_decoder);
719
720 const Byte *buf_start = _buffer + kPad;
721 const Byte *buf_check = buf_start - 4;
722 const Byte *buf = buf_start + litPayloadSize;
723 CBitStream in;
724 if (FseInStream_Init(&in, literal_bits, &buf) != 0)
725 return S_FALSE;
726
727 Byte *lit = _literals;
728 const Byte *lit_limit = lit + numLiterals;
729 for (; lit < lit_limit; lit += 4)
730 {
731 FseInStream_FLUSH
732 DECODE_LIT (lit[0], lit_state_0);
733 DECODE_LIT (lit[1], lit_state_1);
734 FseInStream_FLUSH
735 DECODE_LIT (lit[2], lit_state_2);
736 DECODE_LIT (lit[3], lit_state_3);
737 }
738
739 if ((buf_start - buf) * 8 != (int)in.numBits)
740 return S_FALSE;
741 }
742
743
744 // ---------- Decode LMD ----------
745
746 _buffer.AllocAtLeast(kPad + lmdPayloadSize);
747 memset(_buffer, 0, kPad);
748 if (m_InStream.ReadBytes(_buffer + kPad, lmdPayloadSize) != lmdPayloadSize)
749 return S_FALSE;
750
751 CExtraEntry l_decoder[NUM_L_STATES];
752 CExtraEntry m_decoder[NUM_M_STATES];
753 CExtraEntry d_decoder[NUM_D_STATES];
754
755 InitExtraDecoderTable(NUM_L_STATES, NUM_L_SYMBOLS, freqs_L, k_L_extra, l_decoder);
756 InitExtraDecoderTable(NUM_M_STATES, NUM_M_SYMBOLS, freqs_M, k_M_extra, m_decoder);
757 InitExtraDecoderTable(NUM_D_STATES, NUM_D_SYMBOLS, freqs_D, k_D_extra, d_decoder);
758
759 const Byte *buf_start = _buffer + kPad;
760 const Byte *buf_check = buf_start - 4;
761 const Byte *buf = buf_start + lmdPayloadSize;
762 CBitStream in;
763 if (FseInStream_Init(&in, lmd_bits, &buf))
764 return S_FALSE;
765
766 const Byte *lit = _literals;
767 const Byte *lit_limit = lit + numLiterals;
768
769 UInt32 D = 0;
770
771 for (;;)
772 {
773 if (numMatches == 0)
774 break;
775 numMatches--;
776
777 FseInStream_FLUSH
778
779 unsigned L = (unsigned)FseDecodeExtra(&l_state, l_decoder, &in);
780
781 FseInStream_FLUSH
782
783 unsigned M = (unsigned)FseDecodeExtra(&m_state, m_decoder, &in);
784
785 FseInStream_FLUSH
786
787 {
788 UInt32 new_D = FseDecodeExtra(&d_state, d_decoder, &in);
789 if (new_D)
790 D = new_D;
791 }
792
793 if (L != 0)
794 {
795 if (L > (size_t)(lit_limit - lit))
796 return S_FALSE;
797 unsigned cur = L;
798 if (cur > unpackSize)
799 cur = (unsigned)unpackSize;
800 m_OutWindowStream.PutBytes(lit, cur);
801 unpackSize -= cur;
802 lit += cur;
803 if (cur != L)
804 return S_FALSE;
805 }
806
807 if (M != 0)
808 {
809 if (unpackSize == 0 || D == 0)
810 return S_FALSE;
811 unsigned cur = M;
812 if (cur > unpackSize)
813 cur = (unsigned)unpackSize;
814 if (!m_OutWindowStream.CopyBlock(D - 1, cur))
815 return S_FALSE;
816 unpackSize -= cur;
817 if (cur != M)
818 return S_FALSE;
819 }
820 }
821
822 if (unpackSize != 0)
823 return S_FALSE;
824
825 // LZFSE encoder writes 8 additional zero bytes before LMD payload
826 // We test it:
827 if ((buf - buf_start) * 8 + in.numBits != 64)
828 return S_FALSE;
829 if (GetUi64(buf_start) != 0)
830 return S_FALSE;
831
832 return S_OK;
833 }
834
835
CodeReal(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress)836 STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
837 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
838 {
839 PRF(printf("\n\nLzfseDecoder %7u %7u\n", (unsigned)*outSize, (unsigned)*inSize));
840
841 const UInt32 kLzfseDictSize = 1 << 18;
842 if (!m_OutWindowStream.Create(kLzfseDictSize))
843 return E_OUTOFMEMORY;
844 if (!m_InStream.Create(1 << 18))
845 return E_OUTOFMEMORY;
846
847 m_OutWindowStream.SetStream(outStream);
848 m_OutWindowStream.Init(false);
849 m_InStream.SetStream(inStream);
850 m_InStream.Init();
851
852 CCoderReleaser coderReleaser(this);
853
854 UInt64 prevOut = 0;
855 UInt64 prevIn = 0;
856
857 for (;;)
858 {
859 const UInt64 pos = m_OutWindowStream.GetProcessedSize();
860 const UInt64 packPos = m_InStream.GetProcessedSize();
861
862 if (progress && ((pos - prevOut) >= (1 << 22) || (packPos - prevIn) >= (1 << 22)))
863 {
864 RINOK(progress->SetRatioInfo(&packPos, &pos));
865 prevIn = packPos;
866 prevOut = pos;
867 }
868
869 const UInt64 rem = *outSize - pos;
870 UInt32 v;
871 RINOK(GetUInt32(v))
872 if ((v & 0xFFFFFF) != 0x787662) // bvx
873 return S_FALSE;
874 v >>= 24;
875
876 if (v == 0x24) // '$', end of stream
877 break;
878
879 UInt32 unpackSize;
880 RINOK(GetUInt32(unpackSize));
881
882 UInt32 cur = unpackSize;
883 if (cur > rem)
884 cur = (UInt32)rem;
885
886 unpackSize -= cur;
887
888 HRESULT res;
889 if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2)
890 res = DecodeLzfse(cur, (Byte)v);
891 else if (v == 0x6E) // 'n'
892 res = DecodeLzvn(cur);
893 else if (v == 0x2D) // '-'
894 res = DecodeUncompressed(cur);
895 else
896 return E_NOTIMPL;
897
898 if (res != S_OK)
899 return res;
900
901 if (unpackSize != 0)
902 return S_FALSE;
903 }
904
905 coderReleaser.NeedFlush = false;
906 HRESULT res = m_OutWindowStream.Flush();
907 if (res == S_OK)
908 if (*inSize != m_InStream.GetProcessedSize()
909 || *outSize != m_OutWindowStream.GetProcessedSize())
910 res = S_FALSE;
911 return res;
912 }
913
914
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress)915 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
916 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
917 {
918 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
919 catch(const CInBufferException &e) { return e.ErrorCode; }
920 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
921 catch(...) { return E_OUTOFMEMORY; }
922 // catch(...) { return S_FALSE; }
923 }
924
925 }}
926