1// LZMA/Decoder.h 2 3#ifndef __LZMA_DECODER_H 4#define __LZMA_DECODER_H 5 6#include "../../../Common/MyCom.h" 7#include "../../ICoder.h" 8#include "../LZ/LZOutWindow.h" 9#include "../RangeCoder/RangeCoderBitTree.h" 10 11extern "C" 12{ 13 #include "../../../../C/Alloc.h" 14} 15 16#include "LZMA.h" 17 18namespace NCompress { 19namespace NLZMA { 20 21typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder; 22 23class CLiteralDecoder2 24{ 25 CMyBitDecoder _decoders[0x300]; 26public: 27 void Init() 28 { 29 for (int i = 0; i < 0x300; i++) 30 _decoders[i].Init(); 31 } 32 Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) 33 { 34 UInt32 symbol = 1; 35 RC_INIT_VAR 36 do 37 { 38 // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); 39 RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) 40 } 41 while (symbol < 0x100); 42 RC_FLUSH_VAR 43 return (Byte)symbol; 44 } 45 Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) 46 { 47 UInt32 symbol = 1; 48 RC_INIT_VAR 49 do 50 { 51 UInt32 matchBit = (matchByte >> 7) & 1; 52 matchByte <<= 1; 53 // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); 54 // symbol = (symbol << 1) | bit; 55 UInt32 bit; 56 RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, 57 bit = 0, bit = 1) 58 if (matchBit != bit) 59 { 60 while (symbol < 0x100) 61 { 62 // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); 63 RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) 64 } 65 break; 66 } 67 } 68 while (symbol < 0x100); 69 RC_FLUSH_VAR 70 return (Byte)symbol; 71 } 72}; 73 74class CLiteralDecoder 75{ 76 CLiteralDecoder2 *_coders; 77 int _numPrevBits; 78 int _numPosBits; 79 UInt32 _posMask; 80public: 81 CLiteralDecoder(): _coders(0) {} 82 ~CLiteralDecoder() { Free(); } 83 void Free() 84 { 85 MyFree(_coders); 86 _coders = 0; 87 } 88 bool Create(int numPosBits, int numPrevBits) 89 { 90 if (_coders == 0 || (numPosBits + numPrevBits) != 91 (_numPrevBits + _numPosBits) ) 92 { 93 Free(); 94 UInt32 numStates = 1 << (numPosBits + numPrevBits); 95 _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); 96 } 97 _numPosBits = numPosBits; 98 _posMask = (1 << numPosBits) - 1; 99 _numPrevBits = numPrevBits; 100 return (_coders != 0); 101 } 102 void Init() 103 { 104 UInt32 numStates = 1 << (_numPrevBits + _numPosBits); 105 for (UInt32 i = 0; i < numStates; i++) 106 _coders[i].Init(); 107 } 108 UInt32 GetState(UInt32 pos, Byte prevByte) const 109 { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } 110 Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) 111 { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } 112 Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) 113 { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } 114}; 115 116namespace NLength { 117 118class CDecoder 119{ 120 CMyBitDecoder _choice; 121 CMyBitDecoder _choice2; 122 NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax]; 123 NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax]; 124 NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder; 125public: 126 void Init(UInt32 numPosStates) 127 { 128 _choice.Init(); 129 _choice2.Init(); 130 for (UInt32 posState = 0; posState < numPosStates; posState++) 131 { 132 _lowCoder[posState].Init(); 133 _midCoder[posState].Init(); 134 } 135 _highCoder.Init(); 136 } 137 UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) 138 { 139 if(_choice.Decode(rangeDecoder) == 0) 140 return _lowCoder[posState].Decode(rangeDecoder); 141 if(_choice2.Decode(rangeDecoder) == 0) 142 return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); 143 return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); 144 } 145}; 146 147} 148 149class CDecoder: 150 public ICompressCoder, 151 public ICompressSetDecoderProperties2, 152 public ICompressGetInStreamProcessedSize, 153 #ifndef NO_READ_FROM_CODER 154 public ICompressSetInStream, 155 public ICompressSetOutStreamSize, 156 public ISequentialInStream, 157 #endif 158 public CMyUnknownImp 159{ 160 CLZOutWindow _outWindowStream; 161 NRangeCoder::CDecoder _rangeDecoder; 162 163 CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; 164 CMyBitDecoder _isRep[kNumStates]; 165 CMyBitDecoder _isRepG0[kNumStates]; 166 CMyBitDecoder _isRepG1[kNumStates]; 167 CMyBitDecoder _isRepG2[kNumStates]; 168 CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; 169 170 NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates]; 171 172 CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; 173 NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder; 174 175 NLength::CDecoder _lenDecoder; 176 NLength::CDecoder _repMatchLenDecoder; 177 178 CLiteralDecoder _literalDecoder; 179 180 UInt32 _posStateMask; 181 182 /////////////////// 183 // State 184 UInt32 _reps[4]; 185 CState _state; 186 Int32 _remainLen; // -1 means end of stream. // -2 means need Init 187 UInt64 _outSize; 188 bool _outSizeDefined; 189 190 void Init(); 191 HRESULT CodeSpec(UInt32 size); 192public: 193 194 #ifndef NO_READ_FROM_CODER 195 MY_UNKNOWN_IMP5( 196 ICompressSetDecoderProperties2, 197 ICompressGetInStreamProcessedSize, 198 ICompressSetInStream, 199 ICompressSetOutStreamSize, 200 ISequentialInStream) 201 #else 202 MY_UNKNOWN_IMP2( 203 ICompressSetDecoderProperties2, 204 ICompressGetInStreamProcessedSize) 205 #endif 206 207 void ReleaseStreams() 208 { 209 _outWindowStream.ReleaseStream(); 210 ReleaseInStream(); 211 } 212 213 class CDecoderFlusher 214 { 215 CDecoder *_decoder; 216 public: 217 bool NeedFlush; 218 CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} 219 ~CDecoderFlusher() 220 { 221 if (NeedFlush) 222 _decoder->Flush(); 223 _decoder->ReleaseStreams(); 224 } 225 }; 226 227 HRESULT Flush() { return _outWindowStream.Flush(); } 228 229 STDMETHOD(CodeReal)(ISequentialInStream *inStream, 230 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 231 ICompressProgressInfo *progress); 232 233 STDMETHOD(Code)(ISequentialInStream *inStream, 234 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 235 ICompressProgressInfo *progress); 236 237 STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); 238 STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize); 239 240 STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); 241 242 STDMETHOD(SetInStream)(ISequentialInStream *inStream); 243 STDMETHOD(ReleaseInStream)(); 244 STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); 245 246 #ifndef NO_READ_FROM_CODER 247 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 248 #endif 249 250 CDecoder(): _outSizeDefined(false) {} 251 virtual ~CDecoder() {} 252}; 253 254}} 255 256#endif 257