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 |
|
11 extern "C" |
|
12 { |
|
13 #include "../../../../C/Alloc.h" |
|
14 } |
|
15 |
|
16 #include "LZMA.h" |
|
17 |
|
18 namespace NCompress { |
|
19 namespace NLZMA { |
|
20 |
|
21 typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder; |
|
22 |
|
23 class CLiteralDecoder2 |
|
24 { |
|
25 CMyBitDecoder _decoders[0x300]; |
|
26 public: |
|
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 |
|
74 class CLiteralDecoder |
|
75 { |
|
76 CLiteralDecoder2 *_coders; |
|
77 int _numPrevBits; |
|
78 int _numPosBits; |
|
79 UInt32 _posMask; |
|
80 public: |
|
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 |
|
116 namespace NLength { |
|
117 |
|
118 class 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; |
|
125 public: |
|
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 |
|
149 class 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); |
|
192 public: |
|
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 |
|
239 STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); |
|
240 |
|
241 STDMETHOD(SetInStream)(ISequentialInStream *inStream); |
|
242 STDMETHOD(ReleaseInStream)(); |
|
243 STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); |
|
244 |
|
245 #ifndef NO_READ_FROM_CODER |
|
246 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); |
|
247 #endif |
|
248 |
|
249 CDecoder(): _outSizeDefined(false) {} |
|
250 virtual ~CDecoder() {} |
|
251 }; |
|
252 |
|
253 }} |
|
254 |
|
255 #endif |
|