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