1cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky/* LzmaSpec.c -- LZMA Reference Decoder
2cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky2013-07-28 : Igor Pavlov : Public domain */
3cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
4cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// This code implements LZMA file decoding according to LZMA specification.
5cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// This code is not optimized for speed.
6cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
7cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include <stdio.h>
8cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
9cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifdef _MSC_VER
10cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  #pragma warning(disable : 4710) // function not inlined
11cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  #pragma warning(disable : 4996) // This function or variable may be unsafe
12cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
13cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
14cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckytypedef unsigned char Byte;
15cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckytypedef unsigned short UInt16;
16cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
17cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifdef _LZMA_UINT32_IS_ULONG
18cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  typedef unsigned long UInt32;
19cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#else
20cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  typedef unsigned int UInt32;
21cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
22cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
23cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#if defined(_MSC_VER) || defined(__BORLANDC__)
24cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  typedef unsigned __int64 UInt64;
25cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#else
26cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  typedef unsigned long long int UInt64;
27cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
28cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
29cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
30cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystruct CInputStream
31cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
32cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  FILE *File;
33cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt64 Processed;
34cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
35cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init() { Processed = 0; }
36cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
37cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Byte ReadByte()
38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
39cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    int c = getc(File);
40cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (c < 0)
41cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      throw "Unexpected end of file";
42cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Processed++;
43cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return (Byte)c;
44cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
45cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
46cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
47cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
48cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystruct COutStream
49cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
50cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  FILE *File;
51cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt64 Processed;
52cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
53cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init() { Processed = 0; }
54cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
55cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void WriteByte(Byte b)
56cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
57cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (putc(b, File) == EOF)
58cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      throw "File writing error";
59cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Processed++;
60cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
61cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
62cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
63cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
64cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass COutWindow
65cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
66cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Byte *Buf;
67cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 Pos;
68cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 Size;
69cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool IsFull;
70cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
71cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic:
72cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned TotalPos;
73cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  COutStream OutStream;
74cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
75cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  COutWindow(): Buf(NULL) {}
76cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  ~COutWindow() { delete []Buf; }
77cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
78cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Create(UInt32 dictSize)
79cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
80cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Buf = new Byte[dictSize];
81cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Pos = 0;
82cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Size = dictSize;
83cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    IsFull = false;
84cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    TotalPos = 0;
85cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
86cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
87cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void PutByte(Byte b)
88cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
89cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    TotalPos++;
90cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Buf[Pos++] = b;
91cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (Pos == Size)
92cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
93cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Pos = 0;
94cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      IsFull = true;
95cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
96cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    OutStream.WriteByte(b);
97cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
98cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
99cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Byte GetByte(UInt32 dist) const
100cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
101cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];
102cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
103cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
104cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void CopyMatch(UInt32 dist, unsigned len)
105cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
106cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (; len > 0; len--)
107cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      PutByte(GetByte(dist));
108cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
109cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
110cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool CheckDistance(UInt32 dist) const
111cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
112cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return dist <= Pos || IsFull;
113cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
114cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
115cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool IsEmpty() const
116cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
117cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return Pos == 0 && !IsFull;
118cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
119cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
120cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
121cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
122cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumBitModelTotalBits 11
123cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumMoveBits 5
124cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
125cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckytypedef UInt16 CProb;
126cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)
128cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
129cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define INIT_PROBS(p) \
130cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }
131cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
132cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass CRangeDecoder
133cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
134cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 Range;
135cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 Code;
136cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
137cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Normalize();
138cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
139cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic:
140cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
141cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CInputStream *InStream;
142cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool Corrupted;
143cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
144cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init();
145cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool IsFinishedOK() const { return Code == 0; }
146cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
147cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 DecodeDirectBits(unsigned numBits);
148cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned DecodeBit(CProb *prob);
149cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
150cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
151cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CRangeDecoder::Init()
152cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
153cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Corrupted = false;
154cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
155cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (InStream->ReadByte() != 0)
156cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Corrupted = true;
157cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
158cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Range = 0xFFFFFFFF;
159cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Code = 0;
160cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (int i = 0; i < 4; i++)
161cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Code = (Code << 8) | InStream->ReadByte();
162cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
163cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (Code == Range)
164cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Corrupted = true;
165cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
166cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
167cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kTopValue ((UInt32)1 << 24)
168cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
169cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CRangeDecoder::Normalize()
170cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
171cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (Range < kTopValue)
172cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
173cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Range <<= 8;
174cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Code = (Code << 8) | InStream->ReadByte();
175cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
176cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
177cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
178cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyUInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)
179cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
180cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 res = 0;
181cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  do
182cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
183cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Range >>= 1;
184cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Code -= Range;
185cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    UInt32 t = 0 - ((UInt32)Code >> 31);
186cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Code += Range & t;
187cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
188cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (Code == Range)
189cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Corrupted = true;
190cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
191cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Normalize();
192cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    res <<= 1;
193cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    res += t + 1;
194cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
195cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  while (--numBits);
196cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return res;
197cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
198cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
199cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned CRangeDecoder::DecodeBit(CProb *prob)
200cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
201cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned v = *prob;
202cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 bound = (Range >> kNumBitModelTotalBits) * v;
203cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned symbol;
204cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (Code < bound)
205cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
206cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;
207cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Range = bound;
208cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    symbol = 0;
209cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
210cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else
211cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
212cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    v -= v >> kNumMoveBits;
213cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Code -= bound;
214cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Range -= bound;
215cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    symbol = 1;
216cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
217cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  *prob = (CProb)v;
218cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Normalize();
219cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return symbol;
220cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
221cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
222cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
223cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)
224cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
225cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned m = 1;
226cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned symbol = 0;
227cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (unsigned i = 0; i < numBits; i++)
228cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
229cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned bit = rc->DecodeBit(&probs[m]);
230cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    m <<= 1;
231cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    m += bit;
232cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    symbol |= (bit << i);
233cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
234cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return symbol;
235cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
236cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
237cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckytemplate <unsigned NumBits>
238cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass CBitTreeDecoder
239cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
240cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb Probs[(unsigned)1 << NumBits];
241cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
242cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic:
243cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
244cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init()
245cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
246cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(Probs);
247cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
248cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
249cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned Decode(CRangeDecoder *rc)
250cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
251cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned m = 1;
252cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (unsigned i = 0; i < NumBits; i++)
253cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      m = (m << 1) + rc->DecodeBit(&Probs[m]);
254cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return m - ((unsigned)1 << NumBits);
255cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
256cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
257cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned ReverseDecode(CRangeDecoder *rc)
258cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
259cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return BitTreeReverseDecode(Probs, NumBits, rc);
260cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
261cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
262cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
263cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumPosBitsMax 4
264cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
265cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumStates 12
266cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumLenToPosStates 4
267cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumAlignBits 4
268cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kStartPosModelIndex 4
269cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kEndPosModelIndex 14
270cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
271cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define kMatchMinLen 2
272cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
273cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass CLenDecoder
274cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
275cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb Choice;
276cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb Choice2;
277cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];
278cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];
279cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CBitTreeDecoder<8> HighCoder;
280cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
281cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic:
282cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
283cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init()
284cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
285cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Choice = PROB_INIT_VAL;
286cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Choice2 = PROB_INIT_VAL;
287cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    HighCoder.Init();
288cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)
289cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
290cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      LowCoder[i].Init();
291cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      MidCoder[i].Init();
292cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
293cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
294cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
295cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned Decode(CRangeDecoder *rc, unsigned posState)
296cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
297cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (rc->DecodeBit(&Choice) == 0)
298cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return LowCoder[posState].Decode(rc);
299cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (rc->DecodeBit(&Choice2) == 0)
300cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return 8 + MidCoder[posState].Decode(rc);
301cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return 16 + HighCoder.Decode(rc);
302cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
303cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
304cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
305cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned UpdateState_Literal(unsigned state)
306cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
307cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (state < 4) return 0;
308cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else if (state < 10) return state - 3;
309cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else return state - 6;
310cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
311cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned UpdateState_Match   (unsigned state) { return state < 7 ? 7 : 10; }
312cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned UpdateState_Rep     (unsigned state) { return state < 7 ? 8 : 11; }
313cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyunsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }
314cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
315cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define LZMA_DIC_MIN (1 << 12)
316cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
317cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass CLzmaDecoder
318cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
319cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic:
320cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CRangeDecoder RangeDec;
321cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  COutWindow OutWindow;
322cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
323cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool markerIsMandatory;
324cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned lc, pb, lp;
325cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 dictSize;
326cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 dictSizeInProperties;
327cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
328cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void DecodeProperties(const Byte *properties)
329cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
330cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned d = properties[0];
331cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (d >= (9 * 5 * 5))
332cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      throw "Incorrect LZMA properties";
333cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    lc = d % 9;
334cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    d /= 9;
335cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    pb = d / 5;
336cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    lp = d % 5;
337cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    dictSizeInProperties = 0;
338cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (int i = 0; i < 4; i++)
339cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);
340cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    dictSize = dictSizeInProperties;
341cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (dictSize < LZMA_DIC_MIN)
342cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      dictSize = LZMA_DIC_MIN;
343cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
344cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
345cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CLzmaDecoder(): LitProbs(NULL) {}
346cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  ~CLzmaDecoder() { delete []LitProbs; }
347cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
348cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Create()
349cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
350cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    OutWindow.Create(dictSize);
351cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CreateLiterals();
352cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
353cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
354cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  int Decode(bool unpackSizeDefined, UInt64 unpackSize);
355cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
356cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyprivate:
357cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
358cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb *LitProbs;
359cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
360cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void CreateLiterals()
361cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
362cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];
363cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
364cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
365cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void InitLiterals()
366cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
367cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    UInt32 num = (UInt32)0x300 << (lc + lp);
368cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (UInt32 i = 0; i < num; i++)
369cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      LitProbs[i] = PROB_INIT_VAL;
370cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
371cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
372cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void DecodeLiteral(unsigned state, UInt32 rep0)
373cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
374cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned prevByte = 0;
375cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (!OutWindow.IsEmpty())
376cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      prevByte = OutWindow.GetByte(1);
377cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
378cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned symbol = 1;
379cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));
380cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CProb *probs = &LitProbs[(UInt32)0x300 * litState];
381cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
382cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (state >= 7)
383cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
384cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      unsigned matchByte = OutWindow.GetByte(rep0 + 1);
385cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      do
386cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      {
387cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        unsigned matchBit = (matchByte >> 7) & 1;
388cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        matchByte <<= 1;
389cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);
390cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        symbol = (symbol << 1) | bit;
391cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (matchBit != bit)
392cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          break;
393cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      }
394cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      while (symbol < 0x100);
395cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
396cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    while (symbol < 0x100)
397cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);
398cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    OutWindow.PutByte((Byte)(symbol - 0x100));
399cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
400cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
401cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];
402cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CBitTreeDecoder<kNumAlignBits> AlignDecoder;
403cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];
404cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
405cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void InitDist()
406cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
407cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (unsigned i = 0; i < kNumLenToPosStates; i++)
408cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      PosSlotDecoder[i].Init();
409cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    AlignDecoder.Init();
410cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(PosDecoders);
411cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
412cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
413cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned DecodeDistance(unsigned len)
414cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
415cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned lenState = len;
416cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (lenState > kNumLenToPosStates - 1)
417cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      lenState = kNumLenToPosStates - 1;
418cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
419cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);
420cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (posSlot < 4)
421cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return posSlot;
422cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
423cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);
424cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);
425cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (posSlot < kEndPosModelIndex)
426cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);
427cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    else
428cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
429cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;
430cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      dist += AlignDecoder.ReverseDecode(&RangeDec);
431cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
432cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return dist;
433cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
434cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
435cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsMatch[kNumStates << kNumPosBitsMax];
436cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsRep[kNumStates];
437cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsRepG0[kNumStates];
438cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsRepG1[kNumStates];
439cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsRepG2[kNumStates];
440cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CProb IsRep0Long[kNumStates << kNumPosBitsMax];
441cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
442cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CLenDecoder LenDecoder;
443cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CLenDecoder RepLenDecoder;
444cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
445cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  void Init()
446cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
447cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    InitLiterals();
448cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    InitDist();
449cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
450cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsMatch);
451cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsRep);
452cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsRepG0);
453cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsRepG1);
454cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsRepG2);
455cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    INIT_PROBS(IsRep0Long);
456cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
457cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    LenDecoder.Init();
458cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    RepLenDecoder.Init();
459cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
460cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky};
461cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
462cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
463cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define LZMA_RES_ERROR                   0
464cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define LZMA_RES_FINISHED_WITH_MARKER    1
465cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define LZMA_RES_FINISHED_WITHOUT_MARKER 2
466cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
467cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyint CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)
468cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
469cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Init();
470cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  RangeDec.Init();
471cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
472cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
473cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned state = 0;
474cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
475cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (;;)
476cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
477cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)
478cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (RangeDec.IsFinishedOK())
479cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_FINISHED_WITHOUT_MARKER;
480cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
481cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);
482cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
483cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)
484cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
485cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (unpackSizeDefined && unpackSize == 0)
486cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_ERROR;
487cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      DecodeLiteral(state, rep0);
488cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      state = UpdateState_Literal(state);
489cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      unpackSize--;
490cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      continue;
491cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
492cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
493cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned len;
494cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
495cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (RangeDec.DecodeBit(&IsRep[state]) != 0)
496cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
497cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (unpackSizeDefined && unpackSize == 0)
498cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_ERROR;
499cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (OutWindow.IsEmpty())
500cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_ERROR;
501cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)
502cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      {
503cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)
504cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        {
505cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          state = UpdateState_ShortRep(state);
506cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));
507cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          unpackSize--;
508cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          continue;
509cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        }
510cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      }
511cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      else
512cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      {
513cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        UInt32 dist;
514cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)
515cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          dist = rep1;
516cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        else
517cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        {
518cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)
519cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            dist = rep2;
520cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          else
521cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          {
522cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            dist = rep3;
523cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            rep3 = rep2;
524cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          }
525cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          rep2 = rep1;
526cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        }
527cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        rep1 = rep0;
528cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        rep0 = dist;
529cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      }
530cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      len = RepLenDecoder.Decode(&RangeDec, posState);
531cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      state = UpdateState_Rep(state);
532cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
533cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    else
534cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
535cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      rep3 = rep2;
536cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      rep2 = rep1;
537cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      rep1 = rep0;
538cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      len = LenDecoder.Decode(&RangeDec, posState);
539cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      state = UpdateState_Match(state);
540cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      rep0 = DecodeDistance(len);
541cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (rep0 == 0xFFFFFFFF)
542cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return RangeDec.IsFinishedOK() ?
543cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            LZMA_RES_FINISHED_WITH_MARKER :
544cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            LZMA_RES_ERROR;
545cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
546cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (unpackSizeDefined && unpackSize == 0)
547cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_ERROR;
548cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))
549cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return LZMA_RES_ERROR;
550cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
551cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    len += kMatchMinLen;
552cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    bool isError = false;
553cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (unpackSizeDefined && unpackSize < len)
554cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
555cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      len = (unsigned)unpackSize;
556cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      isError = true;
557cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
558cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    OutWindow.CopyMatch(rep0 + 1, len);
559cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unpackSize -= len;
560cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (isError)
561cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return LZMA_RES_ERROR;
562cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
563cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
564cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
565cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic void Print(const char *s)
566cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
567cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  fputs(s, stdout);
568cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
569cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
570cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic void PrintError(const char *s)
571cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
572cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  fputs(s, stderr);
573cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
574cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
575cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
576cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#define CONVERT_INT_TO_STR(charType, tempSize) \
577cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
578cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid ConvertUInt64ToString(UInt64 val, char *s)
579cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
580cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  char temp[32];
581cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned i = 0;
582cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  while (val >= 10)
583cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
584cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    temp[i++] = (char)('0' + (unsigned)(val % 10));
585cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    val /= 10;
586cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
587cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  *s++ = (char)('0' + (unsigned)val);
588cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  while (i != 0)
589cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
590cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    i--;
591cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    *s++ = temp[i];
592cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
593cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  *s = 0;
594cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
595cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
596cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid PrintUInt64(const char *title, UInt64 v)
597cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
598cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print(title);
599cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print(" : ");
600cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  char s[32];
601cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  ConvertUInt64ToString(v, s);
602cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print(s);
603cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print(" bytes \n");
604cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
605cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
606cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyint main2(int numArgs, const char *args[])
607cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
608cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print("\nLZMA Reference Decoder 9.31 : Igor Pavlov : Public domain : 2013-02-06\n");
609cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (numArgs == 1)
610cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Print("\nUse: lzmaSpec a.lzma outFile");
611cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
612cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (numArgs != 3)
613cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    throw "you must specify two parameters";
614cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
615cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CInputStream inStream;
616cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  inStream.File = fopen(args[1], "rb");
617cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  inStream.Init();
618cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (inStream.File == 0)
619cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    throw "Can't open input file";
620cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
621cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CLzmaDecoder lzmaDecoder;
622cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+");
623cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.OutWindow.OutStream.Init();
624cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (inStream.File == 0)
625cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    throw "Can't open output file";
626cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
627cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Byte header[13];
628cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  int i;
629cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (i = 0; i < 13; i++)
630cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    header[i] = inStream.ReadByte();
631cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
632cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.DecodeProperties(header);
633cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
634cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb);
635cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties);
636cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  printf("\nDictionary Size for decoding  = %u", lzmaDecoder.dictSize);
637cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
638cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt64 unpackSize = 0;
639cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bool unpackSizeDefined = false;
640cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (i = 0; i < 8; i++)
641cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
642cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Byte b = header[5 + i];
643cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (b != 0xFF)
644cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      unpackSizeDefined = true;
645cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unpackSize |= (UInt64)b << (8 * i);
646cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
647cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
648cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.markerIsMandatory = !unpackSizeDefined;
649cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
650cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print("\n");
651cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (unpackSizeDefined)
652cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    PrintUInt64("Uncompressed Size", unpackSize);
653cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else
654cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Print("End marker is expected\n");
655cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.RangeDec.InStream = &inStream;
656cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
657cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print("\n");
658cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
659cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  lzmaDecoder.Create();
660cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  // we support the streams that have uncompressed size and marker.
661cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);
662cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
663cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  PrintUInt64("Read    ", inStream.Processed);
664cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed);
665cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
666cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (res == LZMA_RES_ERROR)
667cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    throw "LZMA decoding error";
668cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER)
669cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Print("Finished without end marker");
670cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else if (res == LZMA_RES_FINISHED_WITH_MARKER)
671cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
672cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (unpackSizeDefined)
673cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
674cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize)
675cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        throw "Finished with end marker before than specified size";
676cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Print("Warning: ");
677cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
678cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Print("Finished with end marker");
679cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
680cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else
681cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    throw "Internal Error";
682cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
683cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Print("\n");
684cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
685cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (lzmaDecoder.RangeDec.Corrupted)
686cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
687cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Print("\nWarning: LZMA stream is corrupted\n");
688cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
689cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
690cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return 0;
691cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
692cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
693cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
694cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyint
695cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  #ifdef _MSC_VER
696cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    __cdecl
697cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  #endif
698cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckymain(int numArgs, const char *args[])
699cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
700cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  try { return main2(numArgs, args); }
701cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  catch (const char *s)
702cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
703cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    PrintError("\nError:\n");
704cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    PrintError(s);
705cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    PrintError("\n");
706cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return 1;
707cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
708cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  catch(...)
709cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
710cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    PrintError("\nError\n");
711cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return 1;
712cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
713cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
714